From 8896a40efcf065d9716f78a67f59f292d1e6171f Mon Sep 17 00:00:00 2001
From: Ray <113240139+Ray-Not@users.noreply.github.com>
Date: Tue, 9 May 2023 23:29:13 +0300
Subject: [PATCH 01/61] Update .gitignore
---
.gitignore | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.gitignore b/.gitignore
index 862eb15..d285d5b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,7 +6,7 @@
# BlueJ files
*.ctxt
-
+#
# Mobile Tools for Java (J2ME)
.mtj.tmp/
@@ -23,4 +23,4 @@
hs_err_pid*
# idea
-.idea
\ No newline at end of file
+.idea
From 1ac519932412281f7fa53d1b89db0a16df605ec2 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Mon, 15 May 2023 14:23:34 +0500
Subject: [PATCH 02/61] Add hw8
---
FP/.github/workflows/bot.yml | 75 ++++++
FP/.github/workflows/scrapper.yml | 74 ++++++
FP/FP/.project | 18 ++
FP/FP/bot/.classpath | 34 +++
.../bot/.dbeaver/.credentials-config.json.bak | Bin 0 -> 112 bytes
FP/FP/bot/.dbeaver/.data-sources.json.bak | 4 +
FP/FP/bot/.dbeaver/.project-metadata.json.bak | 1 +
FP/FP/bot/.dbeaver/data-sources.json | 6 +
FP/FP/bot/.dbeaver/project-metadata.json | 1 +
FP/FP/bot/.dbeaver/project-settings.json | 1 +
FP/FP/bot/.gitignore | 1 +
FP/FP/bot/.project | 24 ++
.../org.eclipse.core.resources.prefs | 6 +
.../bot/.settings/org.eclipse.jdt.core.prefs | 9 +
.../bot/.settings/org.eclipse.m2e.core.prefs | 4 +
FP/FP/bot/pom.xml | 110 ++++++++
.../tinkoff/edu/java/bot/BotApplication.java | 16 ++
.../java/bot/advice/AppExceptionHandler.java | 28 ++
.../edu/java/bot/client/ScrapperClient.java | 103 +++++++
.../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 | 78 ++++++
.../configuration/ClientConfiguration.java | 27 ++
.../LinkParserConfiguration.java | 15 ++
.../configuration/RabbitMQConfiguration.java | 77 ++++++
.../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 | 29 ++
.../bot/service/ScrapperQueueListener.java | 29 ++
.../edu/java/bot/service/UpdateService.java | 8 +
.../java/bot/service/UpdateServiceImpl.java | 26 ++
.../ru/tinkoff/edu/java/bot/telegram/Bot.java | 52 ++++
.../bot/telegram/UserMessageProcessor.java | 126 +++++++++
.../edu/java/bot/telegram/UserState.java | 5 +
.../src/main/resources/application.properties | 14 +
FP/FP/bot/src/test/java/bot/BotTest.java | 123 +++++++++
FP/FP/docker-compose.yml | 60 +++++
FP/FP/link-parser/.classpath | 41 +++
FP/FP/link-parser/.gitignore | 1 +
FP/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/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/FP/migrations/01-schema-1.sql | 11 +
FP/FP/migrations/02-schema-2.sql | 15 ++
FP/FP/migrations/03-schema-3.sql | 10 +
FP/FP/migrations/create.sql | 18 ++
FP/FP/migrations/delete.sql | 3 +
FP/FP/migrations/insert.sql | 37 +++
FP/FP/migrations/master.xml | 13 +
FP/FP/pom.xml | 123 +++++++++
FP/FP/scrapper-jooq/.classpath | 28 ++
FP/FP/scrapper-jooq/.gitignore | 1 +
FP/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/FP/scrapper-jooq/pom.xml | 40 +++
.../src/main/java/JooqCodegen.java | 54 ++++
FP/FP/scrapper/.classpath | 41 +++
FP/FP/scrapper/.gitignore | 1 +
FP/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/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 ++++++++++
167 files changed, 5628 insertions(+)
create mode 100644 FP/.github/workflows/bot.yml
create mode 100644 FP/.github/workflows/scrapper.yml
create mode 100644 FP/FP/.project
create mode 100644 FP/FP/bot/.classpath
create mode 100644 FP/FP/bot/.dbeaver/.credentials-config.json.bak
create mode 100644 FP/FP/bot/.dbeaver/.data-sources.json.bak
create mode 100644 FP/FP/bot/.dbeaver/.project-metadata.json.bak
create mode 100644 FP/FP/bot/.dbeaver/data-sources.json
create mode 100644 FP/FP/bot/.dbeaver/project-metadata.json
create mode 100644 FP/FP/bot/.dbeaver/project-settings.json
create mode 100644 FP/FP/bot/.gitignore
create mode 100644 FP/FP/bot/.project
create mode 100644 FP/FP/bot/.settings/org.eclipse.core.resources.prefs
create mode 100644 FP/FP/bot/.settings/org.eclipse.jdt.core.prefs
create mode 100644 FP/FP/bot/.settings/org.eclipse.m2e.core.prefs
create mode 100644 FP/FP/bot/pom.xml
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java
create mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java
create mode 100644 FP/FP/bot/src/main/resources/application.properties
create mode 100644 FP/FP/bot/src/test/java/bot/BotTest.java
create mode 100644 FP/FP/docker-compose.yml
create mode 100644 FP/FP/link-parser/.classpath
create mode 100644 FP/FP/link-parser/.gitignore
create mode 100644 FP/FP/link-parser/.project
create mode 100644 FP/FP/link-parser/.settings/org.eclipse.core.resources.prefs
create mode 100644 FP/FP/link-parser/.settings/org.eclipse.jdt.core.prefs
create mode 100644 FP/FP/link-parser/.settings/org.eclipse.m2e.core.prefs
create mode 100644 FP/FP/link-parser/pom.xml
create mode 100644 FP/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/GitHub_Link.java
create mode 100644 FP/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/Parser_Link.java
create mode 100644 FP/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/StackOverflow_Link.java
create mode 100644 FP/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java
create mode 100644 FP/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java
create mode 100644 FP/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Link_Parser.java
create mode 100644 FP/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java
create mode 100644 FP/FP/link-parser/src/test/java/LinkParserTest.java
create mode 100644 FP/FP/migrations/01-schema-1.sql
create mode 100644 FP/FP/migrations/02-schema-2.sql
create mode 100644 FP/FP/migrations/03-schema-3.sql
create mode 100644 FP/FP/migrations/create.sql
create mode 100644 FP/FP/migrations/delete.sql
create mode 100644 FP/FP/migrations/insert.sql
create mode 100644 FP/FP/migrations/master.xml
create mode 100644 FP/FP/pom.xml
create mode 100644 FP/FP/scrapper-jooq/.classpath
create mode 100644 FP/FP/scrapper-jooq/.gitignore
create mode 100644 FP/FP/scrapper-jooq/.project
create mode 100644 FP/FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs
create mode 100644 FP/FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs
create mode 100644 FP/FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs
create mode 100644 FP/FP/scrapper-jooq/pom.xml
create mode 100644 FP/FP/scrapper-jooq/src/main/java/JooqCodegen.java
create mode 100644 FP/FP/scrapper/.classpath
create mode 100644 FP/FP/scrapper/.gitignore
create mode 100644 FP/FP/scrapper/.project
create mode 100644 FP/FP/scrapper/.settings/org.eclipse.core.resources.prefs
create mode 100644 FP/FP/scrapper/.settings/org.eclipse.jdt.core.prefs
create mode 100644 FP/FP/scrapper/.settings/org.eclipse.m2e.core.prefs
create mode 100644 FP/FP/scrapper/pom.xml
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java
create mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java
create mode 100644 FP/FP/scrapper/src/main/resources/application.properties
create mode 100644 FP/FP/scrapper/src/main/resources/logback-test.xml
create mode 100644 FP/FP/scrapper/src/test/java/scrapper/DatabaseTest.java
create mode 100644 FP/FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java
create mode 100644 FP/FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java
create mode 100644 FP/FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java
create mode 100644 FP/FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java
create mode 100644 FP/FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java
create mode 100644 FP/FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java
create mode 100644 FP/FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java
diff --git a/FP/.github/workflows/bot.yml b/FP/.github/workflows/bot.yml
new file mode 100644
index 0000000..a693ee2
--- /dev/null
+++ b/FP/.github/workflows/bot.yml
@@ -0,0 +1,75 @@
+name: Bot Actions
+run-name: Bot Pipeline go! π
+on:
+ push:
+ branches: [ "master", "hw9" ]
+ paths:
+ - 'app/bot/**'
+ pull_request:
+ branches: [ "master", "hw9" ]
+ paths:
+ - 'app/bot/**'
+
+env:
+ REGISTRY: ghcr.io
+
+permissions:
+ packages: write
+
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo "π§ This job is now running on a ${{ runner.os }} server hosted by GitHub!"
+ - run: echo "π The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
+
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - run: echo "π‘ The ${{ github.repository }} repository has been cloned to the runner."
+
+ - name: List files in the repository
+ run: |
+ ls ${{ github.workspace }}
+
+ - name: Set up Java 17
+ uses: actions/setup-java@v3
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+ cache: maven
+
+ - name: Build with Maven
+ run: mvn package -pl bot -am
+ working-directory: app
+
+ - name: Build Docker image
+ run: docker build -t ${{ env.REGISTRY }}/${{ github.actor }}/bot-image -f app/bot/Dockerfile .
+
+ - name: Log in to the Container registry
+ uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Push Docker image to GH Packages
+ run: docker push ${{ env.REGISTRY }}/${{ github.actor }}/bot-image
+
+ code-check:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - name: Set up Java 17
+ uses: actions/setup-java@v3
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+ cache: maven
+
+ - name: Build with Maven and check
+ run: mvn package -pl bot -am checkstyle:check
+ working-directory: app
diff --git a/FP/.github/workflows/scrapper.yml b/FP/.github/workflows/scrapper.yml
new file mode 100644
index 0000000..b202d58
--- /dev/null
+++ b/FP/.github/workflows/scrapper.yml
@@ -0,0 +1,74 @@
+name: Scrapper Actions
+run-name: Scrapper Pipeline go! π
+on:
+ push:
+ branches: [ "master", "hw9" ]
+ paths:
+ - 'app/scrapper/**'
+ pull_request:
+ branches: [ "master", "hw9" ]
+ paths:
+ - 'app/scrapper/**'
+
+env:
+ REGISTRY: ghcr.io
+
+permissions:
+ packages: write
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo "π§ This job is now running on a ${{ runner.os }} server hosted by GitHub!"
+ - run: echo "π The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
+
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - run: echo "π‘ The ${{ github.repository }} repository has been cloned to the runner."
+
+ - name: List files in the repository
+ run: |
+ ls -la ${{ github.workspace }}
+
+ - name: Set up Java 17
+ uses: actions/setup-java@v3
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+ cache: maven
+
+ - name: Build with Maven
+ run: mvn package -pl scrapper -am
+ working-directory: app
+
+ - name: Build Docker image
+ run: docker build -t ${{ env.REGISTRY }}/${{ github.actor }}/scrapper-image -f app/scrapper/Dockerfile .
+
+ - name: Log in to the Container registry
+ uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Push Docker image to GH Packages
+ run: docker push ${{ env.REGISTRY }}/${{ github.actor }}/scrapper-image
+
+ code-check:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - name: Set up Java 17
+ uses: actions/setup-java@v3
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+ cache: maven
+
+ - name: Build with Maven and check
+ run: mvn package -pl scrapper -am checkstyle:check
+ working-directory: app
diff --git a/FP/FP/.project b/FP/FP/.project
new file mode 100644
index 0000000..89d138f
--- /dev/null
+++ b/FP/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/FP/bot/.classpath b/FP/FP/bot/.classpath
new file mode 100644
index 0000000..0b9fa8d
--- /dev/null
+++ b/FP/FP/bot/.classpath
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FP/FP/bot/.dbeaver/.credentials-config.json.bak b/FP/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/FP/bot/.settings/org.eclipse.core.resources.prefs b/FP/FP/bot/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..29abf99
--- /dev/null
+++ b/FP/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/FP/bot/.settings/org.eclipse.jdt.core.prefs b/FP/FP/bot/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..5e4ec05
--- /dev/null
+++ b/FP/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/FP/bot/.settings/org.eclipse.m2e.core.prefs b/FP/FP/bot/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/FP/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/FP/bot/pom.xml b/FP/FP/bot/pom.xml
new file mode 100644
index 0000000..7d7818b
--- /dev/null
+++ b/FP/FP/bot/pom.xml
@@ -0,0 +1,110 @@
+
+ 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
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+
+ ../checkstyle.xml
+
+
+
+
+
\ No newline at end of file
diff --git a/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java
new file mode 100644
index 0000000..50cd2b8
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java
new file mode 100644
index 0000000..8ff54fd
--- /dev/null
+++ b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java
@@ -0,0 +1,28 @@
+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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java
new file mode 100644
index 0000000..c8b8bab
--- /dev/null
+++ b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java
@@ -0,0 +1,103 @@
+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;
+
+ private final String wentWrongMessage = "Π§ΡΠΎ-ΡΠΎ ΠΏΠΎΡΠ»ΠΎ Π½Π΅ ΡΠ°ΠΊ. ΠΡΠΎΠ±Π»Π΅ΠΌΠ° Π½Π° Π½Π°ΡΠ΅ΠΉ ΡΡΠΎΡΠΎΠ½Π΅, ΠΏΠΎΠ²ΡΠΎΡΠΈΡΠ΅ ΠΏΠΎΠΏΡΡΠΊΡ ΠΏΠΎΠ·ΠΆΠ΅";
+
+ //ΠΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ - 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(
+ wentWrongMessage);
+ }
+ 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(
+ wentWrongMessage);
+ }
+ 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(
+ wentWrongMessage);
+ }
+ 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(
+ wentWrongMessage);
+ }
+ 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(
+ wentWrongMessage);
+ }
+ return Mono.empty();
+ }).block();
+ }
+
+}
\ No newline at end of file
diff --git a/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java
new file mode 100644
index 0000000..9ef91d4
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java
new file mode 100644
index 0000000..a179c88
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java
new file mode 100644
index 0000000..1d3852c
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java
new file mode 100644
index 0000000..b8e8b62
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java
new file mode 100644
index 0000000..6a3176e
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java
new file mode 100644
index 0000000..98da89f
--- /dev/null
+++ b/FP/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();
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java
new file mode 100644
index 0000000..fed745d
--- /dev/null
+++ b/FP/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 Link_Parser 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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java
new file mode 100644
index 0000000..df1c58a
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java
new file mode 100644
index 0000000..02ab1d4
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java
new file mode 100644
index 0000000..31177f6
--- /dev/null
+++ b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java
@@ -0,0 +1,78 @@
+package ru.tinkoff.edu.java.bot.configuration;
+
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+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.Command;
+import ru.tinkoff.edu.java.bot.commands.CommandsEnum;
+import ru.tinkoff.edu.java.bot.commands.HelpCommand;
+import ru.tinkoff.edu.java.bot.commands.ListCommand;
+import ru.tinkoff.edu.java.bot.commands.StartCommand;
+import ru.tinkoff.edu.java.bot.commands.TrackCommand;
+import ru.tinkoff.edu.java.bot.commands.UntrackCommand;
+import ru.tinkoff.edu.java.bot.dto.BotCommand;
+import ru.tinkoff.edu.java.bot.dto.SetCommandRequest;
+import ru.tinkoff.edu.java.bot.telegram.Bot;
+
+@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);
+
+ //ΠΠ΅Π»Π°Π΅ΠΌ ΠΊΠ½ΠΎΠΏΠΊΡ "ΠΠ΅Π½Ρ" ΡΡΠ΄ΠΎΠΌ Ρ ΠΈΠΊΠΎΠ½ΠΊΠΎΠΉ ΡΠΊΡΠ΅ΠΏΠΊΠΈ
+ //Π½ΡΠΆΠ½ΠΎ ΠΎΡΠΏΡΠ°Π²ΠΈΡΡ Π·Π°ΠΏΡΠΎΡ Π½Π° API ΡΠ΅Π»Π΅Π³ΡΠ°ΠΌΠΌΠ° (ΠΌΠ΅ΡΠΎΠ΄ setMyCommands) ΡΠΎ ΡΠΏΠΈΡΠΊΠΎΠΌ ΠΊΠΎΠΌΠ°Π½Π΄ Π² Π²ΠΈΠ΄Π΅ List
+ 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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java
new file mode 100644
index 0000000..f5d3a09
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java
new file mode 100644
index 0000000..eea3511
--- /dev/null
+++ b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java
@@ -0,0 +1,15 @@
+package ru.tinkoff.edu.java.bot.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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java
new file mode 100644
index 0000000..fb0772c
--- /dev/null
+++ b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java
@@ -0,0 +1,77 @@
+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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java
new file mode 100644
index 0000000..1ff0bee
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java
new file mode 100644
index 0000000..d8d6113
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java
new file mode 100644
index 0000000..201c5c6
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java
new file mode 100644
index 0000000..2ab0a84
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java
new file mode 100644
index 0000000..396f750
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java
new file mode 100644
index 0000000..8a92e00
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java
new file mode 100644
index 0000000..5d23d7b
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java
new file mode 100644
index 0000000..7e58ba4
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java
new file mode 100644
index 0000000..799cdc3
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java
new file mode 100644
index 0000000..d21ec6a
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java
new file mode 100644
index 0000000..524f6f3
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java
new file mode 100644
index 0000000..98c36ae
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java
new file mode 100644
index 0000000..2120e54
--- /dev/null
+++ b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java
@@ -0,0 +1,29 @@
+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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java
new file mode 100644
index 0000000..3cdef00
--- /dev/null
+++ b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java
@@ -0,0 +1,29 @@
+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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java
new file mode 100644
index 0000000..ed22af0
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java
new file mode 100644
index 0000000..0e0531d
--- /dev/null
+++ b/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java
new file mode 100644
index 0000000..050e804
--- /dev/null
+++ b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java
@@ -0,0 +1,52 @@
+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 lombok.extern.slf4j.Slf4j;
+import ru.tinkoff.edu.java.bot.commands.Command;
+import ru.tinkoff.edu.java.bot.commands.CommandsEnum;
+
+import java.util.EnumMap;
+
+@Slf4j
+public class Bot implements AutoCloseable {
+
+ private final TelegramBot bot;
+ private final UserMessageProcessor userMessageProcessor;
+
+ @PostConstruct
+ public void init() {
+ start();
+ }
+
+ public Bot(String token, EnumMap commands) {
+ log.info("Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ Π±ΠΎΡΠ°... Π’ΠΎΠΊΠ΅Π½: " + token);
+ userMessageProcessor = new UserMessageProcessor(commands);
+ bot = new TelegramBot(token);
+ }
+
+ public void start() {
+ log.info("ΠΠΎΡ Π·Π°ΠΏΡΡΠ΅Π½...");
+ bot.setUpdatesListener(updates -> {
+ for (Update update : updates) {
+ if (update.message() != null) {
+ 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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java
new file mode 100644
index 0000000..ac7b8ac
--- /dev/null
+++ b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java
@@ -0,0 +1,126 @@
+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 List commands;
+
+ // Π‘ΠΎΡΡΠΎΡΠ½ΠΈΠ΅ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ. ΠΡΠΆΠ½ΠΎ Π΄Π»Ρ ΡΠ΄ΠΎΠ±Π½ΠΎΠΉ ΡΠ°Π±ΠΎΡΡ Ρ ΠΊΠΎΠΌΠ°Π½Π΄Π°ΠΌΠΈ /track ΠΈ /untrack
+ // TYPING_COMMAND - ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ Π²Π²ΠΎΠ΄Π° ΠΊΠΎΠΌΠ°Π½Π΄Ρ (ΠΏΠΎ-ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ)
+ // TYPING_TRACKED - ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ Π²Π²ΠΎΠ΄Π° ΡΡΡΠ»ΠΊΠΈ Π΄Π»Ρ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΡ
+ // TYPING_UNTRACKED - ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ Π²Π²ΠΎΠ΄Π° ΡΡΡΠ»ΠΊΠΈ Π΄Π»Ρ ΡΠ΄Π°Π»Π΅Π½ΠΈΡ
+ 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 Π½ΠΈΠΊΠ°ΠΊ Π½Π΅Π΄ΠΎΡΡΠΈΠΆΠΈΠΌ
+ return "Π§ΡΠΎ-ΡΠΎ ΠΏΠΎΡΠ»ΠΎ Π½Π΅ ΡΠ°ΠΊ. ΠΡΠΎΠ±Π»Π΅ΠΌΠ° Π½Π° Π½Π°ΡΠ΅ΠΉ ΡΡΠΎΡΠΎΠ½Π΅";
+
+ }
+ }
+
+ }
+
+ }vate 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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java
new file mode 100644
index 0000000..70bc584
--- /dev/null
+++ b/FP/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/FP/bot/src/main/resources/application.properties b/FP/FP/bot/src/main/resources/application.properties
new file mode 100644
index 0000000..bf1fbc5
--- /dev/null
+++ b/FP/FP/bot/src/main/resources/application.properties
@@ -0,0 +1,14 @@
+app.test=beamer-bot
+server.port=8080
+springdoc.swagger-ui.path=/swagger-ui
+scrapper.baseurl=http://localhost:8080
+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=2281337
+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/FP/bot/src/test/java/bot/BotTest.java b/FP/FP/bot/src/test/java/bot/BotTest.java
new file mode 100644
index 0000000..af954d2
--- /dev/null
+++ b/FP/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/FP/docker-compose.yml b/FP/FP/docker-compose.yml
new file mode 100644
index 0000000..c472659
--- /dev/null
+++ b/FP/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/FP/link-parser/.classpath b/FP/FP/link-parser/.classpath
new file mode 100644
index 0000000..a08fc4f
--- /dev/null
+++ b/FP/FP/link-parser/.classpath
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FP/FP/link-parser/.gitignore b/FP/FP/link-parser/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/FP/FP/link-parser/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/FP/FP/link-parser/.project b/FP/FP/link-parser/.project
new file mode 100644
index 0000000..dec0f32
--- /dev/null
+++ b/FP/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/FP/link-parser/.settings/org.eclipse.core.resources.prefs b/FP/FP/link-parser/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..29abf99
--- /dev/null
+++ b/FP/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/FP/link-parser/.settings/org.eclipse.jdt.core.prefs b/FP/FP/link-parser/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..5e4ec05
--- /dev/null
+++ b/FP/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/FP/link-parser/.settings/org.eclipse.m2e.core.prefs b/FP/FP/link-parser/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/FP/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/FP/link-parser/pom.xml b/FP/FP/link-parser/pom.xml
new file mode 100644
index 0000000..3cfd292
--- /dev/null
+++ b/FP/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/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/GitHub_Link.java b/FP/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/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/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/Parser_Link.java b/FP/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/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/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/StackOverflow_Link.java b/FP/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/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/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java b/FP/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/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/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java b/FP/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/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/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Link_Parser.java b/FP/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/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/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java b/FP/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/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/FP/link-parser/src/test/java/LinkParserTest.java b/FP/FP/link-parser/src/test/java/LinkParserTest.java
new file mode 100644
index 0000000..bef7512
--- /dev/null
+++ b/FP/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/FP/migrations/01-schema-1.sql b/FP/FP/migrations/01-schema-1.sql
new file mode 100644
index 0000000..838947b
--- /dev/null
+++ b/FP/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/FP/migrations/02-schema-2.sql b/FP/FP/migrations/02-schema-2.sql
new file mode 100644
index 0000000..0e40afb
--- /dev/null
+++ b/FP/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/FP/migrations/03-schema-3.sql b/FP/FP/migrations/03-schema-3.sql
new file mode 100644
index 0000000..c407b73
--- /dev/null
+++ b/FP/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/FP/migrations/create.sql b/FP/FP/migrations/create.sql
new file mode 100644
index 0000000..a4e2a68
--- /dev/null
+++ b/FP/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/FP/migrations/delete.sql b/FP/FP/migrations/delete.sql
new file mode 100644
index 0000000..1fb56bd
--- /dev/null
+++ b/FP/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/FP/migrations/insert.sql b/FP/FP/migrations/insert.sql
new file mode 100644
index 0000000..30b59be
--- /dev/null
+++ b/FP/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/FP/migrations/master.xml b/FP/FP/migrations/master.xml
new file mode 100644
index 0000000..c566afc
--- /dev/null
+++ b/FP/FP/migrations/master.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FP/FP/pom.xml b/FP/FP/pom.xml
new file mode 100644
index 0000000..a1baa3d
--- /dev/null
+++ b/FP/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/FP/scrapper-jooq/.classpath b/FP/FP/scrapper-jooq/.classpath
new file mode 100644
index 0000000..ead1d0f
--- /dev/null
+++ b/FP/FP/scrapper-jooq/.classpath
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FP/FP/scrapper-jooq/.gitignore b/FP/FP/scrapper-jooq/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/FP/FP/scrapper-jooq/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/FP/FP/scrapper-jooq/.project b/FP/FP/scrapper-jooq/.project
new file mode 100644
index 0000000..f320f87
--- /dev/null
+++ b/FP/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/FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs b/FP/FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..609d3ca
--- /dev/null
+++ b/FP/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/FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs b/FP/FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..5e4ec05
--- /dev/null
+++ b/FP/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/FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs b/FP/FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/FP/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/FP/scrapper-jooq/pom.xml b/FP/FP/scrapper-jooq/pom.xml
new file mode 100644
index 0000000..b6f0785
--- /dev/null
+++ b/FP/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/FP/scrapper-jooq/src/main/java/JooqCodegen.java b/FP/FP/scrapper-jooq/src/main/java/JooqCodegen.java
new file mode 100644
index 0000000..f8a5bc7
--- /dev/null
+++ b/FP/FP/scrapper-jooq/src/main/java/JooqCodegen.java
@@ -0,0 +1,54 @@
+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 final class JooqCodegen {
+
+ private 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/FP/scrapper/.classpath b/FP/FP/scrapper/.classpath
new file mode 100644
index 0000000..a08fc4f
--- /dev/null
+++ b/FP/FP/scrapper/.classpath
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FP/FP/scrapper/.gitignore b/FP/FP/scrapper/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/FP/FP/scrapper/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/FP/FP/scrapper/.project b/FP/FP/scrapper/.project
new file mode 100644
index 0000000..d56fd66
--- /dev/null
+++ b/FP/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/FP/scrapper/.settings/org.eclipse.core.resources.prefs b/FP/FP/scrapper/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..29abf99
--- /dev/null
+++ b/FP/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/FP/scrapper/.settings/org.eclipse.jdt.core.prefs b/FP/FP/scrapper/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..5e4ec05
--- /dev/null
+++ b/FP/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/FP/scrapper/.settings/org.eclipse.m2e.core.prefs b/FP/FP/scrapper/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/FP/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/FP/scrapper/pom.xml b/FP/FP/scrapper/pom.xml
new file mode 100644
index 0000000..1b0c4fa
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
new file mode 100644
index 0000000..fef7338
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java
new file mode 100644
index 0000000..2e1aacf
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java
new file mode 100644
index 0000000..021e3ec
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java
new file mode 100644
index 0000000..156cf35
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java
new file mode 100644
index 0000000..6651dd9
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
new file mode 100644
index 0000000..856e54e
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java
new file mode 100644
index 0000000..8694acf
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java
new file mode 100644
index 0000000..df6780e
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java
new file mode 100644
index 0000000..e400f15
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
new file mode 100644
index 0000000..d8b1217
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java
new file mode 100644
index 0000000..97985ba
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java
new file mode 100644
index 0000000..7c065be
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java
new file mode 100644
index 0000000..8f6367c
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java
new file mode 100644
index 0000000..cadc95f
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java
new file mode 100644
index 0000000..1b6410a
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java
new file mode 100644
index 0000000..a142f3a
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java
new file mode 100644
index 0000000..09a3867
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java
new file mode 100644
index 0000000..9e2f0b9
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java
new file mode 100644
index 0000000..50227fc
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java
new file mode 100644
index 0000000..58d769c
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java
new file mode 100644
index 0000000..d5be7a4
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java
new file mode 100644
index 0000000..9ee4d12
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java
new file mode 100644
index 0000000..5dd1124
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java
new file mode 100644
index 0000000..29dc8cf
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java
new file mode 100644
index 0000000..9bf30c3
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java
new file mode 100644
index 0000000..58a7dfb
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java
new file mode 100644
index 0000000..e5c5c62
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java
new file mode 100644
index 0000000..e714110
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java
new file mode 100644
index 0000000..72df1e2
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java
new file mode 100644
index 0000000..bd76b2b
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java
new file mode 100644
index 0000000..4597040
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java
new file mode 100644
index 0000000..388ebac
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java
new file mode 100644
index 0000000..5aef3ac
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java
new file mode 100644
index 0000000..eec99f7
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java
new file mode 100644
index 0000000..623f12b
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java
new file mode 100644
index 0000000..91471de
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java
new file mode 100644
index 0000000..61ee96d
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java b/FP/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/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java b/FP/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/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/FP/scrapper/src/main/resources/application.properties b/FP/FP/scrapper/src/main/resources/application.properties
new file mode 100644
index 0000000..3761f00
--- /dev/null
+++ b/FP/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/FP/scrapper/src/main/resources/logback-test.xml b/FP/FP/scrapper/src/main/resources/logback-test.xml
new file mode 100644
index 0000000..900637e
--- /dev/null
+++ b/FP/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/FP/scrapper/src/test/java/scrapper/DatabaseTest.java b/FP/FP/scrapper/src/test/java/scrapper/DatabaseTest.java
new file mode 100644
index 0000000..1c2378c
--- /dev/null
+++ b/FP/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/FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java b/FP/FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java
new file mode 100644
index 0000000..2f0bdfa
--- /dev/null
+++ b/FP/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/FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java b/FP/FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java
new file mode 100644
index 0000000..d0ac18a
--- /dev/null
+++ b/FP/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/FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java b/FP/FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java
new file mode 100644
index 0000000..416b086
--- /dev/null
+++ b/FP/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/FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java b/FP/FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java
new file mode 100644
index 0000000..a4ff395
--- /dev/null
+++ b/FP/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/FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java b/FP/FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java
new file mode 100644
index 0000000..436f01a
--- /dev/null
+++ b/FP/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/FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java b/FP/FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java
new file mode 100644
index 0000000..0813c59
--- /dev/null
+++ b/FP/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/FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java b/FP/FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java
new file mode 100644
index 0000000..df7d245
--- /dev/null
+++ b/FP/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 522ae1ead7de26dcbbc23412130726eff8907df2 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Mon, 15 May 2023 14:25:46 +0500
Subject: [PATCH 03/61] Rework
---
FP/FP/.project | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/FP/FP/.project b/FP/FP/.project
index 89d138f..7b5c63d 100644
--- a/FP/FP/.project
+++ b/FP/FP/.project
@@ -1,6 +1,6 @@
- project
+ FP
From b85b2010ebabb6fd1edf2b2f208999d4a19cfc61 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Fri, 19 May 2023 19:01:18 +0500
Subject: [PATCH 04/61] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=BD=D0=B5?=
=?UTF-8?q?=D1=81=20=D1=81=208=20=D0=BF=D1=80=D0=B0=D0=BA=D1=82=D0=B8?=
=?UTF-8?q?=D0=BA=D0=B8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 9 +-
FP/.github/workflows/bot.yml | 75 ------
FP/.github/workflows/scrapper.yml | 74 ------
FP/FP/.project | 18 --
FP/FP/bot/.classpath | 34 ---
.../bot/.dbeaver/.credentials-config.json.bak | Bin 112 -> 0 bytes
FP/FP/bot/.dbeaver/.data-sources.json.bak | 4 -
FP/FP/bot/.dbeaver/.project-metadata.json.bak | 1 -
FP/FP/bot/.dbeaver/data-sources.json | 6 -
FP/FP/bot/.dbeaver/project-metadata.json | 1 -
FP/FP/bot/.dbeaver/project-settings.json | 1 -
FP/FP/bot/.gitignore | 1 -
FP/FP/bot/.project | 24 --
.../org.eclipse.core.resources.prefs | 6 -
.../bot/.settings/org.eclipse.jdt.core.prefs | 9 -
.../bot/.settings/org.eclipse.m2e.core.prefs | 4 -
FP/FP/bot/pom.xml | 110 --------
.../tinkoff/edu/java/bot/BotApplication.java | 16 --
.../java/bot/advice/AppExceptionHandler.java | 28 --
.../edu/java/bot/client/ScrapperClient.java | 103 -------
.../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 | 78 ------
.../configuration/ClientConfiguration.java | 27 --
.../LinkParserConfiguration.java | 15 --
.../configuration/RabbitMQConfiguration.java | 77 ------
.../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 | 29 --
.../bot/service/ScrapperQueueListener.java | 29 --
.../edu/java/bot/service/UpdateService.java | 8 -
.../java/bot/service/UpdateServiceImpl.java | 26 --
.../ru/tinkoff/edu/java/bot/telegram/Bot.java | 52 ----
.../bot/telegram/UserMessageProcessor.java | 126 ---------
.../edu/java/bot/telegram/UserState.java | 5 -
.../src/main/resources/application.properties | 14 -
FP/FP/bot/src/test/java/bot/BotTest.java | 123 ---------
FP/FP/docker-compose.yml | 60 -----
FP/FP/link-parser/.classpath | 41 ---
FP/FP/link-parser/.gitignore | 1 -
FP/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/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/FP/migrations/01-schema-1.sql | 11 -
FP/FP/migrations/02-schema-2.sql | 15 --
FP/FP/migrations/03-schema-3.sql | 10 -
FP/FP/migrations/create.sql | 18 --
FP/FP/migrations/delete.sql | 3 -
FP/FP/migrations/insert.sql | 37 ---
FP/FP/scrapper-jooq/.classpath | 28 --
FP/FP/scrapper-jooq/.gitignore | 1 -
FP/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/FP/scrapper-jooq/pom.xml | 40 ---
.../src/main/java/JooqCodegen.java | 54 ----
FP/FP/scrapper/.classpath | 41 ---
FP/FP/scrapper/.gitignore | 1 -
FP/FP/scrapper/.project | 23 --
.../org.eclipse.core.resources.prefs | 6 -
.../.settings/org.eclipse.jdt.core.prefs | 9 -
.../.settings/org.eclipse.m2e.core.prefs | 4 -
.../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 --
.../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 ----------
FP/bot/pom.xml | 110 ++++++++
.../tinkoff/edu/java/bot/BotApplication.java | 26 ++
.../edu/java/bot/api/BotController.java | 14 +
.../exceptionHandler/BotExceptionHandler.java | 36 +++
.../configuration/RabbitMQConfiguration.java | 56 ++++
.../edu/java/bot/configuration/jdbcBean.java | 26 ++
.../records/ApplicationConfig.java | 22 ++
.../java/bot/configuration/records/Bot.java | 4 +
.../bot/configuration/records/Scheduler.java | 5 +
.../tinkoff/edu/java/bot/handler/BotMain.java | 33 +++
.../ru/tinkoff/edu/java/bot/handler/DB.java | 42 +++
.../edu/java/bot/handler/MessageHandler.java | 39 +++
.../tinkoff/edu/java/bot/handler/Updater.java | 44 +++
.../edu/java/bot/handler/commands/All.java | 7 +
.../edu/java/bot/handler/commands/Help.java | 11 +
.../edu/java/bot/handler/commands/List.java | 37 +++
.../edu/java/bot/handler/commands/Start.java | 19 ++
.../edu/java/bot/handler/commands/Track.java | 47 ++++
.../java/bot/handler/commands/Untrack.java | 24 ++
.../edu/java/bot/model/ApiErrorResponse.java | 11 +
.../edu/java/bot/model/LinkUpdate.java | 6 +
.../bot/schedule/LinkUpdaterScheduler.java | 17 ++
.../src/main/resources/application.properties | 9 +
FP/docker-compose.yml | 54 ++++
FP/link-parser/pom.xml | 26 ++
.../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 | 24 ++
FP/migrations/chats_links_scheme.sql | 8 +
FP/{FP => }/migrations/master.xml | 4 +-
FP/{FP => }/pom.xml | 151 +++++------
FP/{FP => }/scrapper/pom.xml | 86 +++---
.../java/scrapper/ScrapperApplication.java | 29 ++
.../scrapper/api/ScrapperControllerLinks.java | 46 ++++
.../scrapper/api/ScrapperControllerTg.java | 29 ++
.../scrapper/client/ClientConfiguration.java | 57 ++++
.../java/scrapper/client/GitHubRecord.java | 19 ++
.../scrapper/client/StackOverflowRecord.java | 10 +
.../java/scrapper/client/WeatherRecord.java | 11 +
.../configuration/ApplicationConfig.java | 37 +++
.../configuration/RabbitMQConfiguration.java | 71 +++++
.../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 | 81 ++++++
.../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/model/AddLinkRequest.java | 3 +
.../edu/java/scrapper/model/ChatResponse.java | 3 +
.../java/scrapper/model/LinkChatResponse.java | 3 +
.../edu/java/scrapper/model/LinkResponse.java | 3 +
.../edu/java/scrapper/model/LinkUpdate.java | 4 +
.../scrapper/model/ListLinksResponse.java | 6 +
.../scrapper/model/RemoveLinkRequest.java | 3 +
.../java/scrapper/model/UpdateService.java | 4 +
.../HandleNoticeServiceImplement.java | 5 +
.../rabbitmq/HandleNoticeServiceQueue.java | 16 ++
.../rabbitmq/ScrapperQueueListener.java | 19 ++
.../rabbitmq/ScrapperQueueProducer.java | 28 ++
.../rabbitmq/SendNoticeServiceHttp.java | 11 +
.../rabbitmq/SendNoticeServiceImplement.java | 5 +
.../rabbitmq/SendNoticeServiceQueue.java | 20 ++
.../schedule/LinkUpdaterScheduler.java | 63 +++++
.../edu/java/scrapper/schedule/Scheduler.java | 3 +-
.../src/main/resources/application.properties | 9 +
FP/scrapper/src/test/java/BaseTest.java | 11 +
.../src/test/java/IntegrationEnvironment.java | 45 ++++
FP/scrapper/src/test/java/JdbcAddTest.java | 9 +
README.md | 0
246 files changed, 2058 insertions(+), 5497 deletions(-)
delete mode 100644 FP/.github/workflows/bot.yml
delete mode 100644 FP/.github/workflows/scrapper.yml
delete mode 100644 FP/FP/.project
delete mode 100644 FP/FP/bot/.classpath
delete mode 100644 FP/FP/bot/.dbeaver/.credentials-config.json.bak
delete mode 100644 FP/FP/bot/.dbeaver/.data-sources.json.bak
delete mode 100644 FP/FP/bot/.dbeaver/.project-metadata.json.bak
delete mode 100644 FP/FP/bot/.dbeaver/data-sources.json
delete mode 100644 FP/FP/bot/.dbeaver/project-metadata.json
delete mode 100644 FP/FP/bot/.dbeaver/project-settings.json
delete mode 100644 FP/FP/bot/.gitignore
delete mode 100644 FP/FP/bot/.project
delete mode 100644 FP/FP/bot/.settings/org.eclipse.core.resources.prefs
delete mode 100644 FP/FP/bot/.settings/org.eclipse.jdt.core.prefs
delete mode 100644 FP/FP/bot/.settings/org.eclipse.m2e.core.prefs
delete mode 100644 FP/FP/bot/pom.xml
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java
delete mode 100644 FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java
delete mode 100644 FP/FP/bot/src/main/resources/application.properties
delete mode 100644 FP/FP/bot/src/test/java/bot/BotTest.java
delete mode 100644 FP/FP/docker-compose.yml
delete mode 100644 FP/FP/link-parser/.classpath
delete mode 100644 FP/FP/link-parser/.gitignore
delete mode 100644 FP/FP/link-parser/.project
delete mode 100644 FP/FP/link-parser/.settings/org.eclipse.core.resources.prefs
delete mode 100644 FP/FP/link-parser/.settings/org.eclipse.jdt.core.prefs
delete mode 100644 FP/FP/link-parser/.settings/org.eclipse.m2e.core.prefs
delete mode 100644 FP/FP/link-parser/pom.xml
delete mode 100644 FP/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/GitHub_Link.java
delete mode 100644 FP/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/Parser_Link.java
delete mode 100644 FP/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/StackOverflow_Link.java
delete mode 100644 FP/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java
delete mode 100644 FP/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java
delete mode 100644 FP/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Link_Parser.java
delete mode 100644 FP/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java
delete mode 100644 FP/FP/link-parser/src/test/java/LinkParserTest.java
delete mode 100644 FP/FP/migrations/01-schema-1.sql
delete mode 100644 FP/FP/migrations/02-schema-2.sql
delete mode 100644 FP/FP/migrations/03-schema-3.sql
delete mode 100644 FP/FP/migrations/create.sql
delete mode 100644 FP/FP/migrations/delete.sql
delete mode 100644 FP/FP/migrations/insert.sql
delete mode 100644 FP/FP/scrapper-jooq/.classpath
delete mode 100644 FP/FP/scrapper-jooq/.gitignore
delete mode 100644 FP/FP/scrapper-jooq/.project
delete mode 100644 FP/FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs
delete mode 100644 FP/FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs
delete mode 100644 FP/FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs
delete mode 100644 FP/FP/scrapper-jooq/pom.xml
delete mode 100644 FP/FP/scrapper-jooq/src/main/java/JooqCodegen.java
delete mode 100644 FP/FP/scrapper/.classpath
delete mode 100644 FP/FP/scrapper/.gitignore
delete mode 100644 FP/FP/scrapper/.project
delete mode 100644 FP/FP/scrapper/.settings/org.eclipse.core.resources.prefs
delete mode 100644 FP/FP/scrapper/.settings/org.eclipse.jdt.core.prefs
delete mode 100644 FP/FP/scrapper/.settings/org.eclipse.m2e.core.prefs
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java
delete mode 100644 FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java
delete mode 100644 FP/FP/scrapper/src/main/resources/application.properties
delete mode 100644 FP/FP/scrapper/src/main/resources/logback-test.xml
delete mode 100644 FP/FP/scrapper/src/test/java/scrapper/DatabaseTest.java
delete mode 100644 FP/FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java
delete mode 100644 FP/FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java
delete mode 100644 FP/FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java
delete mode 100644 FP/FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java
delete mode 100644 FP/FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java
delete mode 100644 FP/FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java
delete mode 100644 FP/FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java
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/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/configuration/RabbitMQConfiguration.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/jdbcBean.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/ApplicationConfig.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/Bot.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/Scheduler.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/BotMain.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/DB.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/MessageHandler.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/Updater.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/All.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Help.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/List.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Start.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Track.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Untrack.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/model/ApiErrorResponse.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/model/LinkUpdate.java
create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/schedule/LinkUpdaterScheduler.java
create mode 100644 FP/bot/src/main/resources/application.properties
create mode 100644 FP/docker-compose.yml
create mode 100644 FP/link-parser/pom.xml
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
create mode 100644 FP/link-parser/src/test/java/LinkParserTest.java
create mode 100644 FP/migrations/chats_links_scheme.sql
rename FP/{FP => }/migrations/master.xml (83%)
rename FP/{FP => }/pom.xml (65%)
rename FP/{FP => }/scrapper/pom.xml (69%)
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/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/client/ClientConfiguration.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubRecord.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
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/RabbitMQConfiguration.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
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/AddLinkRequest.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/ChatResponse.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkChatResponse.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkResponse.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkUpdate.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/ListLinksResponse.java
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/RemoveLinkRequest.java
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/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.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
create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdaterScheduler.java
rename FP/{FP => }/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java (62%)
create mode 100644 FP/scrapper/src/main/resources/application.properties
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
create mode 100644 README.md
diff --git a/.gitignore b/.gitignore
index d285d5b..f87b265 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,13 @@
# Compiled class file
*.class
+
# Log file
*.log
# BlueJ files
*.ctxt
-#
+
# Mobile Tools for Java (J2ME)
.mtj.tmp/
@@ -23,4 +24,8 @@
hs_err_pid*
# idea
-.idea
+FP/.idea/
+
+# volumes
+FP/migrations/postgres_data/
+FP/rabbitmq/
\ No newline at end of file
diff --git a/FP/.github/workflows/bot.yml b/FP/.github/workflows/bot.yml
deleted file mode 100644
index a693ee2..0000000
--- a/FP/.github/workflows/bot.yml
+++ /dev/null
@@ -1,75 +0,0 @@
-name: Bot Actions
-run-name: Bot Pipeline go! π
-on:
- push:
- branches: [ "master", "hw9" ]
- paths:
- - 'app/bot/**'
- pull_request:
- branches: [ "master", "hw9" ]
- paths:
- - 'app/bot/**'
-
-env:
- REGISTRY: ghcr.io
-
-permissions:
- packages: write
-
-
-jobs:
- build:
- runs-on: ubuntu-latest
- steps:
- - run: echo "π§ This job is now running on a ${{ runner.os }} server hosted by GitHub!"
- - run: echo "π The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
-
- - name: Checkout repository
- uses: actions/checkout@v3
-
- - run: echo "π‘ The ${{ github.repository }} repository has been cloned to the runner."
-
- - name: List files in the repository
- run: |
- ls ${{ github.workspace }}
-
- - name: Set up Java 17
- uses: actions/setup-java@v3
- with:
- java-version: '17'
- distribution: 'temurin'
- cache: maven
-
- - name: Build with Maven
- run: mvn package -pl bot -am
- working-directory: app
-
- - name: Build Docker image
- run: docker build -t ${{ env.REGISTRY }}/${{ github.actor }}/bot-image -f app/bot/Dockerfile .
-
- - name: Log in to the Container registry
- uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
- with:
- registry: ${{ env.REGISTRY }}
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Push Docker image to GH Packages
- run: docker push ${{ env.REGISTRY }}/${{ github.actor }}/bot-image
-
- code-check:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout repository
- uses: actions/checkout@v3
-
- - name: Set up Java 17
- uses: actions/setup-java@v3
- with:
- java-version: '17'
- distribution: 'temurin'
- cache: maven
-
- - name: Build with Maven and check
- run: mvn package -pl bot -am checkstyle:check
- working-directory: app
diff --git a/FP/.github/workflows/scrapper.yml b/FP/.github/workflows/scrapper.yml
deleted file mode 100644
index b202d58..0000000
--- a/FP/.github/workflows/scrapper.yml
+++ /dev/null
@@ -1,74 +0,0 @@
-name: Scrapper Actions
-run-name: Scrapper Pipeline go! π
-on:
- push:
- branches: [ "master", "hw9" ]
- paths:
- - 'app/scrapper/**'
- pull_request:
- branches: [ "master", "hw9" ]
- paths:
- - 'app/scrapper/**'
-
-env:
- REGISTRY: ghcr.io
-
-permissions:
- packages: write
-
-jobs:
- build:
- runs-on: ubuntu-latest
- steps:
- - run: echo "π§ This job is now running on a ${{ runner.os }} server hosted by GitHub!"
- - run: echo "π The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
-
- - name: Checkout repository
- uses: actions/checkout@v3
-
- - run: echo "π‘ The ${{ github.repository }} repository has been cloned to the runner."
-
- - name: List files in the repository
- run: |
- ls -la ${{ github.workspace }}
-
- - name: Set up Java 17
- uses: actions/setup-java@v3
- with:
- java-version: '17'
- distribution: 'temurin'
- cache: maven
-
- - name: Build with Maven
- run: mvn package -pl scrapper -am
- working-directory: app
-
- - name: Build Docker image
- run: docker build -t ${{ env.REGISTRY }}/${{ github.actor }}/scrapper-image -f app/scrapper/Dockerfile .
-
- - name: Log in to the Container registry
- uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
- with:
- registry: ${{ env.REGISTRY }}
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Push Docker image to GH Packages
- run: docker push ${{ env.REGISTRY }}/${{ github.actor }}/scrapper-image
-
- code-check:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout repository
- uses: actions/checkout@v3
-
- - name: Set up Java 17
- uses: actions/setup-java@v3
- with:
- java-version: '17'
- distribution: 'temurin'
- cache: maven
-
- - name: Build with Maven and check
- run: mvn package -pl scrapper -am checkstyle:check
- working-directory: app
diff --git a/FP/FP/.project b/FP/FP/.project
deleted file mode 100644
index 7b5c63d..0000000
--- a/FP/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/FP/bot/.classpath b/FP/FP/bot/.classpath
deleted file mode 100644
index 0b9fa8d..0000000
--- a/FP/FP/bot/.classpath
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/FP/FP/bot/.dbeaver/.credentials-config.json.bak b/FP/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/FP/bot/.settings/org.eclipse.core.resources.prefs b/FP/FP/bot/.settings/org.eclipse.core.resources.prefs
deleted file mode 100644
index 29abf99..0000000
--- a/FP/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/FP/bot/.settings/org.eclipse.jdt.core.prefs b/FP/FP/bot/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 5e4ec05..0000000
--- a/FP/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/FP/bot/.settings/org.eclipse.m2e.core.prefs b/FP/FP/bot/.settings/org.eclipse.m2e.core.prefs
deleted file mode 100644
index f897a7f..0000000
--- a/FP/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/FP/bot/pom.xml b/FP/FP/bot/pom.xml
deleted file mode 100644
index 7d7818b..0000000
--- a/FP/FP/bot/pom.xml
+++ /dev/null
@@ -1,110 +0,0 @@
-
- 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
-
-
- org.apache.maven.plugins
- maven-checkstyle-plugin
-
- ../checkstyle.xml
-
-
-
-
-
\ No newline at end of file
diff --git a/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java
deleted file mode 100644
index 50cd2b8..0000000
--- a/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java
+++ /dev/null
@@ -1,16 +0,0 @@
-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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java
deleted file mode 100644
index 8ff54fd..0000000
--- a/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java
+++ /dev/null
@@ -1,28 +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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java
deleted file mode 100644
index c8b8bab..0000000
--- a/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java
+++ /dev/null
@@ -1,103 +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;
-
- private final String wentWrongMessage = "Π§ΡΠΎ-ΡΠΎ ΠΏΠΎΡΠ»ΠΎ Π½Π΅ ΡΠ°ΠΊ. ΠΡΠΎΠ±Π»Π΅ΠΌΠ° Π½Π° Π½Π°ΡΠ΅ΠΉ ΡΡΠΎΡΠΎΠ½Π΅, ΠΏΠΎΠ²ΡΠΎΡΠΈΡΠ΅ ΠΏΠΎΠΏΡΡΠΊΡ ΠΏΠΎΠ·ΠΆΠ΅";
-
- //ΠΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ - 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(
- wentWrongMessage);
- }
- 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(
- wentWrongMessage);
- }
- 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(
- wentWrongMessage);
- }
- 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(
- wentWrongMessage);
- }
- 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(
- wentWrongMessage);
- }
- return Mono.empty();
- }).block();
- }
-
-}
\ No newline at end of file
diff --git a/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java
deleted file mode 100644
index 9ef91d4..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java
deleted file mode 100644
index a179c88..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java
deleted file mode 100644
index 1d3852c..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java
deleted file mode 100644
index b8e8b62..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java
deleted file mode 100644
index 6a3176e..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java
deleted file mode 100644
index 98da89f..0000000
--- a/FP/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();
- }
-
- }
-}
\ No newline at end of file
diff --git a/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java
deleted file mode 100644
index fed745d..0000000
--- a/FP/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 Link_Parser 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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java
deleted file mode 100644
index df1c58a..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java
deleted file mode 100644
index 02ab1d4..0000000
--- a/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java
+++ /dev/null
@@ -1,12 +0,0 @@
-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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java
deleted file mode 100644
index 31177f6..0000000
--- a/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package ru.tinkoff.edu.java.bot.configuration;
-
-import java.util.ArrayList;
-import java.util.EnumMap;
-import java.util.List;
-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.Command;
-import ru.tinkoff.edu.java.bot.commands.CommandsEnum;
-import ru.tinkoff.edu.java.bot.commands.HelpCommand;
-import ru.tinkoff.edu.java.bot.commands.ListCommand;
-import ru.tinkoff.edu.java.bot.commands.StartCommand;
-import ru.tinkoff.edu.java.bot.commands.TrackCommand;
-import ru.tinkoff.edu.java.bot.commands.UntrackCommand;
-import ru.tinkoff.edu.java.bot.dto.BotCommand;
-import ru.tinkoff.edu.java.bot.dto.SetCommandRequest;
-import ru.tinkoff.edu.java.bot.telegram.Bot;
-
-@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);
-
- //ΠΠ΅Π»Π°Π΅ΠΌ ΠΊΠ½ΠΎΠΏΠΊΡ "ΠΠ΅Π½Ρ" ΡΡΠ΄ΠΎΠΌ Ρ ΠΈΠΊΠΎΠ½ΠΊΠΎΠΉ ΡΠΊΡΠ΅ΠΏΠΊΠΈ
- //Π½ΡΠΆΠ½ΠΎ ΠΎΡΠΏΡΠ°Π²ΠΈΡΡ Π·Π°ΠΏΡΠΎΡ Π½Π° API ΡΠ΅Π»Π΅Π³ΡΠ°ΠΌΠΌΠ° (ΠΌΠ΅ΡΠΎΠ΄ setMyCommands) ΡΠΎ ΡΠΏΠΈΡΠΊΠΎΠΌ ΠΊΠΎΠΌΠ°Π½Π΄ Π² Π²ΠΈΠ΄Π΅ List
- 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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java
deleted file mode 100644
index f5d3a09..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java
deleted file mode 100644
index eea3511..0000000
--- a/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package ru.tinkoff.edu.java.bot.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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java
deleted file mode 100644
index fb0772c..0000000
--- a/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java
+++ /dev/null
@@ -1,77 +0,0 @@
-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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java
deleted file mode 100644
index 1ff0bee..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java
deleted file mode 100644
index d8d6113..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java
deleted file mode 100644
index 201c5c6..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java
deleted file mode 100644
index 2ab0a84..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java
deleted file mode 100644
index 396f750..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java
deleted file mode 100644
index 8a92e00..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java
deleted file mode 100644
index 5d23d7b..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java
deleted file mode 100644
index 7e58ba4..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java
deleted file mode 100644
index 799cdc3..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java
deleted file mode 100644
index d21ec6a..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java
deleted file mode 100644
index 524f6f3..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java
deleted file mode 100644
index 98c36ae..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java
deleted file mode 100644
index 2120e54..0000000
--- a/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java
+++ /dev/null
@@ -1,29 +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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java
deleted file mode 100644
index 3cdef00..0000000
--- a/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java
+++ /dev/null
@@ -1,29 +0,0 @@
-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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java
deleted file mode 100644
index ed22af0..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java
deleted file mode 100644
index 0e0531d..0000000
--- a/FP/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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java
deleted file mode 100644
index 050e804..0000000
--- a/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java
+++ /dev/null
@@ -1,52 +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 lombok.extern.slf4j.Slf4j;
-import ru.tinkoff.edu.java.bot.commands.Command;
-import ru.tinkoff.edu.java.bot.commands.CommandsEnum;
-
-import java.util.EnumMap;
-
-@Slf4j
-public class Bot implements AutoCloseable {
-
- private final TelegramBot bot;
- private final UserMessageProcessor userMessageProcessor;
-
- @PostConstruct
- public void init() {
- start();
- }
-
- public Bot(String token, EnumMap commands) {
- log.info("Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ Π±ΠΎΡΠ°... Π’ΠΎΠΊΠ΅Π½: " + token);
- userMessageProcessor = new UserMessageProcessor(commands);
- bot = new TelegramBot(token);
- }
-
- public void start() {
- log.info("ΠΠΎΡ Π·Π°ΠΏΡΡΠ΅Π½...");
- bot.setUpdatesListener(updates -> {
- for (Update update : updates) {
- if (update.message() != null) {
- 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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java
deleted file mode 100644
index ac7b8ac..0000000
--- a/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java
+++ /dev/null
@@ -1,126 +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 List commands;
-
- // Π‘ΠΎΡΡΠΎΡΠ½ΠΈΠ΅ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ. ΠΡΠΆΠ½ΠΎ Π΄Π»Ρ ΡΠ΄ΠΎΠ±Π½ΠΎΠΉ ΡΠ°Π±ΠΎΡΡ Ρ ΠΊΠΎΠΌΠ°Π½Π΄Π°ΠΌΠΈ /track ΠΈ /untrack
- // TYPING_COMMAND - ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ Π²Π²ΠΎΠ΄Π° ΠΊΠΎΠΌΠ°Π½Π΄Ρ (ΠΏΠΎ-ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ)
- // TYPING_TRACKED - ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ Π²Π²ΠΎΠ΄Π° ΡΡΡΠ»ΠΊΠΈ Π΄Π»Ρ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΡ
- // TYPING_UNTRACKED - ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ Π²Π²ΠΎΠ΄Π° ΡΡΡΠ»ΠΊΠΈ Π΄Π»Ρ ΡΠ΄Π°Π»Π΅Π½ΠΈΡ
- 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 Π½ΠΈΠΊΠ°ΠΊ Π½Π΅Π΄ΠΎΡΡΠΈΠΆΠΈΠΌ
- return "Π§ΡΠΎ-ΡΠΎ ΠΏΠΎΡΠ»ΠΎ Π½Π΅ ΡΠ°ΠΊ. ΠΡΠΎΠ±Π»Π΅ΠΌΠ° Π½Π° Π½Π°ΡΠ΅ΠΉ ΡΡΠΎΡΠΎΠ½Π΅";
-
- }
- }
-
- }
-
- }vate 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/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java b/FP/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java
deleted file mode 100644
index 70bc584..0000000
--- a/FP/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/FP/bot/src/main/resources/application.properties b/FP/FP/bot/src/main/resources/application.properties
deleted file mode 100644
index bf1fbc5..0000000
--- a/FP/FP/bot/src/main/resources/application.properties
+++ /dev/null
@@ -1,14 +0,0 @@
-app.test=beamer-bot
-server.port=8080
-springdoc.swagger-ui.path=/swagger-ui
-scrapper.baseurl=http://localhost:8080
-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=2281337
-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/FP/bot/src/test/java/bot/BotTest.java b/FP/FP/bot/src/test/java/bot/BotTest.java
deleted file mode 100644
index af954d2..0000000
--- a/FP/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/FP/docker-compose.yml b/FP/FP/docker-compose.yml
deleted file mode 100644
index c472659..0000000
--- a/FP/FP/docker-compose.yml
+++ /dev/null
@@ -1,60 +0,0 @@
-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/FP/link-parser/.classpath b/FP/FP/link-parser/.classpath
deleted file mode 100644
index a08fc4f..0000000
--- a/FP/FP/link-parser/.classpath
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/FP/FP/link-parser/.gitignore b/FP/FP/link-parser/.gitignore
deleted file mode 100644
index b83d222..0000000
--- a/FP/FP/link-parser/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/target/
diff --git a/FP/FP/link-parser/.project b/FP/FP/link-parser/.project
deleted file mode 100644
index dec0f32..0000000
--- a/FP/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/FP/link-parser/.settings/org.eclipse.core.resources.prefs b/FP/FP/link-parser/.settings/org.eclipse.core.resources.prefs
deleted file mode 100644
index 29abf99..0000000
--- a/FP/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/FP/link-parser/.settings/org.eclipse.jdt.core.prefs b/FP/FP/link-parser/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 5e4ec05..0000000
--- a/FP/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/FP/link-parser/.settings/org.eclipse.m2e.core.prefs b/FP/FP/link-parser/.settings/org.eclipse.m2e.core.prefs
deleted file mode 100644
index f897a7f..0000000
--- a/FP/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/FP/link-parser/pom.xml b/FP/FP/link-parser/pom.xml
deleted file mode 100644
index 3cfd292..0000000
--- a/FP/FP/link-parser/pom.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
- 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/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/GitHub_Link.java b/FP/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/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/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/Parser_Link.java b/FP/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/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/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/StackOverflow_Link.java b/FP/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/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/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java b/FP/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java
deleted file mode 100644
index f3641fc..0000000
--- a/FP/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/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java b/FP/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java
deleted file mode 100644
index 13ae325..0000000
--- a/FP/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/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Link_Parser.java b/FP/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/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/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java b/FP/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java
deleted file mode 100644
index e224578..0000000
--- a/FP/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/FP/link-parser/src/test/java/LinkParserTest.java b/FP/FP/link-parser/src/test/java/LinkParserTest.java
deleted file mode 100644
index bef7512..0000000
--- a/FP/FP/link-parser/src/test/java/LinkParserTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-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/FP/migrations/01-schema-1.sql b/FP/FP/migrations/01-schema-1.sql
deleted file mode 100644
index 838947b..0000000
--- a/FP/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/FP/migrations/02-schema-2.sql b/FP/FP/migrations/02-schema-2.sql
deleted file mode 100644
index 0e40afb..0000000
--- a/FP/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/FP/migrations/03-schema-3.sql b/FP/FP/migrations/03-schema-3.sql
deleted file mode 100644
index c407b73..0000000
--- a/FP/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/FP/migrations/create.sql b/FP/FP/migrations/create.sql
deleted file mode 100644
index a4e2a68..0000000
--- a/FP/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/FP/migrations/delete.sql b/FP/FP/migrations/delete.sql
deleted file mode 100644
index 1fb56bd..0000000
--- a/FP/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/FP/migrations/insert.sql b/FP/FP/migrations/insert.sql
deleted file mode 100644
index 30b59be..0000000
--- a/FP/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/FP/scrapper-jooq/.classpath b/FP/FP/scrapper-jooq/.classpath
deleted file mode 100644
index ead1d0f..0000000
--- a/FP/FP/scrapper-jooq/.classpath
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/FP/FP/scrapper-jooq/.gitignore b/FP/FP/scrapper-jooq/.gitignore
deleted file mode 100644
index b83d222..0000000
--- a/FP/FP/scrapper-jooq/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/target/
diff --git a/FP/FP/scrapper-jooq/.project b/FP/FP/scrapper-jooq/.project
deleted file mode 100644
index f320f87..0000000
--- a/FP/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/FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs b/FP/FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs
deleted file mode 100644
index 609d3ca..0000000
--- a/FP/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/FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs b/FP/FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 5e4ec05..0000000
--- a/FP/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/FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs b/FP/FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs
deleted file mode 100644
index f897a7f..0000000
--- a/FP/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/FP/scrapper-jooq/pom.xml b/FP/FP/scrapper-jooq/pom.xml
deleted file mode 100644
index b6f0785..0000000
--- a/FP/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/FP/scrapper-jooq/src/main/java/JooqCodegen.java b/FP/FP/scrapper-jooq/src/main/java/JooqCodegen.java
deleted file mode 100644
index f8a5bc7..0000000
--- a/FP/FP/scrapper-jooq/src/main/java/JooqCodegen.java
+++ /dev/null
@@ -1,54 +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 final class JooqCodegen {
-
- private 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/FP/scrapper/.classpath b/FP/FP/scrapper/.classpath
deleted file mode 100644
index a08fc4f..0000000
--- a/FP/FP/scrapper/.classpath
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/FP/FP/scrapper/.gitignore b/FP/FP/scrapper/.gitignore
deleted file mode 100644
index b83d222..0000000
--- a/FP/FP/scrapper/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/target/
diff --git a/FP/FP/scrapper/.project b/FP/FP/scrapper/.project
deleted file mode 100644
index d56fd66..0000000
--- a/FP/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/FP/scrapper/.settings/org.eclipse.core.resources.prefs b/FP/FP/scrapper/.settings/org.eclipse.core.resources.prefs
deleted file mode 100644
index 29abf99..0000000
--- a/FP/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/FP/scrapper/.settings/org.eclipse.jdt.core.prefs b/FP/FP/scrapper/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 5e4ec05..0000000
--- a/FP/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/FP/scrapper/.settings/org.eclipse.m2e.core.prefs b/FP/FP/scrapper/.settings/org.eclipse.m2e.core.prefs
deleted file mode 100644
index f897a7f..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
deleted file mode 100644
index fef7338..0000000
--- a/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
+++ /dev/null
@@ -1,22 +0,0 @@
-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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java
deleted file mode 100644
index 2e1aacf..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java
deleted file mode 100644
index 021e3ec..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java
deleted file mode 100644
index 156cf35..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java
deleted file mode 100644
index 6651dd9..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
deleted file mode 100644
index 856e54e..0000000
--- a/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
+++ /dev/null
@@ -1,26 +0,0 @@
-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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java
deleted file mode 100644
index 8694acf..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java
deleted file mode 100644
index df6780e..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java
deleted file mode 100644
index e400f15..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
deleted file mode 100644
index d8b1217..0000000
--- a/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
+++ /dev/null
@@ -1,50 +0,0 @@
-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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java
deleted file mode 100644
index d70f747..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java
deleted file mode 100644
index 47864de..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java
deleted file mode 100644
index ff97aba..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java
deleted file mode 100644
index 97985ba..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java
deleted file mode 100644
index 7c065be..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java
deleted file mode 100644
index 8f6367c..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java
deleted file mode 100644
index cadc95f..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java
deleted file mode 100644
index 1b6410a..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java
deleted file mode 100644
index a142f3a..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java
deleted file mode 100644
index 09a3867..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java
deleted file mode 100644
index 9e2f0b9..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java
deleted file mode 100644
index 50227fc..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java
deleted file mode 100644
index 58d769c..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java
deleted file mode 100644
index d5be7a4..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java
deleted file mode 100644
index 9ee4d12..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java
deleted file mode 100644
index 5dd1124..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java
deleted file mode 100644
index 29dc8cf..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java
deleted file mode 100644
index 9bf30c3..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java
deleted file mode 100644
index 58a7dfb..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java
deleted file mode 100644
index e5c5c62..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java
deleted file mode 100644
index e714110..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java
deleted file mode 100644
index 72df1e2..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java
deleted file mode 100644
index bd76b2b..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java
deleted file mode 100644
index 4597040..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java
deleted file mode 100644
index 59b4a92..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java
deleted file mode 100644
index 74f7693..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java
deleted file mode 100644
index abe684a..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java
deleted file mode 100644
index bd4469b..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java
deleted file mode 100644
index 8f49d40..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java
deleted file mode 100644
index 38d0931..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java
deleted file mode 100644
index fce7af7..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java
deleted file mode 100644
index d59d09c..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java
deleted file mode 100644
index 0298278..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java
deleted file mode 100644
index 0dde7e4..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java
deleted file mode 100644
index 87cbf34..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java
deleted file mode 100644
index 7371ffd..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java
deleted file mode 100644
index 6463de4..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java
deleted file mode 100644
index d942314..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java
deleted file mode 100644
index 2f1dab8..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java
deleted file mode 100644
index cdcb762..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java
deleted file mode 100644
index 388ebac..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java
deleted file mode 100644
index 5aef3ac..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java
deleted file mode 100644
index eec99f7..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java
deleted file mode 100644
index 91471de..0000000
--- a/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java
+++ /dev/null
@@ -1,26 +0,0 @@
-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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java
deleted file mode 100644
index 61ee96d..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java
deleted file mode 100644
index 10646d7..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java
deleted file mode 100644
index b35caad..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java
deleted file mode 100644
index adf1fde..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java
deleted file mode 100644
index 983fdb9..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java
deleted file mode 100644
index 4476e8b..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java
deleted file mode 100644
index 84a130a..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java
deleted file mode 100644
index f27d081..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java
deleted file mode 100644
index c5c9749..0000000
--- a/FP/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/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java b/FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java
deleted file mode 100644
index b87e274..0000000
--- a/FP/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/FP/scrapper/src/main/resources/application.properties b/FP/FP/scrapper/src/main/resources/application.properties
deleted file mode 100644
index 3761f00..0000000
--- a/FP/FP/scrapper/src/main/resources/application.properties
+++ /dev/null
@@ -1,23 +0,0 @@
-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/FP/scrapper/src/main/resources/logback-test.xml b/FP/FP/scrapper/src/main/resources/logback-test.xml
deleted file mode 100644
index 900637e..0000000
--- a/FP/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/FP/scrapper/src/test/java/scrapper/DatabaseTest.java b/FP/FP/scrapper/src/test/java/scrapper/DatabaseTest.java
deleted file mode 100644
index 1c2378c..0000000
--- a/FP/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/FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java b/FP/FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java
deleted file mode 100644
index 2f0bdfa..0000000
--- a/FP/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/FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java b/FP/FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java
deleted file mode 100644
index d0ac18a..0000000
--- a/FP/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/FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java b/FP/FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java
deleted file mode 100644
index 416b086..0000000
--- a/FP/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/FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java b/FP/FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java
deleted file mode 100644
index a4ff395..0000000
--- a/FP/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/FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java b/FP/FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java
deleted file mode 100644
index 436f01a..0000000
--- a/FP/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/FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java b/FP/FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java
deleted file mode 100644
index 0813c59..0000000
--- a/FP/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/FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java b/FP/FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java
deleted file mode 100644
index df7d245..0000000
--- a/FP/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/FP/bot/pom.xml b/FP/bot/pom.xml
new file mode 100644
index 0000000..96dea0d
--- /dev/null
+++ b/FP/bot/pom.xml
@@ -0,0 +1,110 @@
+
+
+
+ org.example
+ FP
+ 1.0
+
+
+ 4.0.0
+
+ bot
+
+
+ 3.0.1
+ 2.7.6
+
+
+
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ 2.1.0
+
+
+ org.apache.commons
+ commons-lang3
+ 3.10
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+ ${starter-validation.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ ${starter-web.version}
+
+
+ org.apache.logging.log4j
+ log4j-to-slf4j
+
+
+
+
+ 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
+
+
+
+ com.github.pengrad
+ java-telegram-bot-api
+ 6.6.0
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.2
+
+
+
+ org.springframework.boot
+ 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
new file mode 100644
index 0000000..92ae210
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java
@@ -0,0 +1,26 @@
+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)
+public class BotApplication
+{
+ public static void main(String[] args){
+ var ctx = SpringApplication.run(BotApplication.class, args);
+ ApplicationConfig config = ctx.getBean(ApplicationConfig.class);
+ 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/api/BotController.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/BotController.java
new file mode 100644
index 0000000..6a559cf
--- /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.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..5beb1bd
--- /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.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/configuration/RabbitMQConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java
new file mode 100644
index 0000000..1616669
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java
@@ -0,0 +1,56 @@
+package ru.tinkoff.edu.java.bot.configuration;
+
+import org.springframework.amqp.core.*;
+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 java.util.Collections;
+
+@Configuration
+public class RabbitMQConfiguration {
+
+ private final ApplicationConfig config;
+
+ public RabbitMQConfiguration(ApplicationConfig config) {
+ this.config = config;
+ }
+
+ @Bean
+ public DirectExchange exchange() {
+ return new DirectExchange(config.exchange());
+ }
+
+ @Bean
+ public Queue 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());
+ }
+
+ @Bean
+ public DirectExchange dlqExchange() {
+ return new DirectExchange(config.exchange() + ".dlq");
+ }
+
+ @Bean
+ public Queue dlqQueue() {
+ return QueueBuilder.durable(config.queue() + ".dlq").build();
+ }
+
+ @Bean
+ public Binding dlqBinding() {
+ return BindingBuilder.bind(dlqQueue())
+ .to(dlqExchange())
+ .with(config.routingKey());
+ }
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..c23d07b
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/ApplicationConfig.java
@@ -0,0 +1,22 @@
+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,
+ @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/records/Scheduler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/Scheduler.java
new file mode 100644
index 0000000..daed115
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/Scheduler.java
@@ -0,0 +1,5 @@
+package ru.tinkoff.edu.java.bot.configuration.records;
+
+import java.time.Duration;
+
+public record Scheduler(Duration interval) {}
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
new file mode 100644
index 0000000..13d6b65
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/BotMain.java
@@ -0,0 +1,33 @@
+package ru.tinkoff.edu.java.bot.handler;
+
+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, JdbcTemplate jdbcTemplate) {
+ this.token = token;
+ this.jdbcTemplate = jdbcTemplate;
+ }
+
+ public void start() {
+ bot = new TelegramBot(token);
+ bot.setUpdatesListener(new Updater(bot, jdbcTemplate));
+ }
+
+ public void end() {
+ bot.removeGetUpdatesListener();
+ }
+}
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/DB.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/DB.java
new file mode 100644
index 0000000..6b57338
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/DB.java
@@ -0,0 +1,42 @@
+package ru.tinkoff.edu.java.bot.handler;
+
+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/handler/MessageHandler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/MessageHandler.java
new file mode 100644
index 0000000..87f2ab0
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/MessageHandler.java
@@ -0,0 +1,39 @@
+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(jdbcTemplate, chatid);
+ case "/help" -> help();
+ 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(jdbcTemplate, chatid);
+ case "/help" -> help();
+ 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
new file mode 100644
index 0000000..7965170
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/Updater.java
@@ -0,0 +1,44 @@
+package ru.tinkoff.edu.java.bot.handler;
+
+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 org.springframework.jdbc.core.JdbcTemplate;
+
+import java.util.List;
+
+public class Updater implements UpdatesListener {
+
+ MessageHandler handler;
+ String command;
+ TelegramBot bot;
+ private JdbcTemplate jdbcTemplate;
+ private long chatid;
+
+ 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]);
+ 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/handler/commands/All.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/All.java
new file mode 100644
index 0000000..5f63723
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/All.java
@@ -0,0 +1,7 @@
+package ru.tinkoff.edu.java.bot.handler.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/handler/commands/Help.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Help.java
new file mode 100644
index 0000000..4d0da5a
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Help.java
@@ -0,0 +1,11 @@
+package ru.tinkoff.edu.java.bot.handler.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/handler/commands/List.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/List.java
new file mode 100644
index 0000000..280f80a
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/List.java
@@ -0,0 +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;
+
+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
new file mode 100644
index 0000000..d2d5459
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Start.java
@@ -0,0 +1,19 @@
+package ru.tinkoff.edu.java.bot.handler.commands;
+
+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(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
new file mode 100644
index 0000000..9080b48
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Track.java
@@ -0,0 +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 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
new file mode 100644
index 0000000..6615feb
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Untrack.java
@@ -0,0 +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 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 "ΠΠ΅ΡΠ΅Π΄ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ Π½ΡΠΆΠ½ΠΎ Π·Π°ΡΠ΅Π³ΠΈΡΡΡΠΈΡΠΎΠ²Π°ΡΡΡΡ";
+ }
+ 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/java/ru/tinkoff/edu/java/bot/model/ApiErrorResponse.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/model/ApiErrorResponse.java
new file mode 100644
index 0000000..57e1c06
--- /dev/null
+++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/model/ApiErrorResponse.java
@@ -0,0 +1,11 @@
+package ru.tinkoff.edu.java.bot.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/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/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/resources/application.properties b/FP/bot/src/main/resources/application.properties
new file mode 100644
index 0000000..6600aaa
--- /dev/null
+++ b/FP/bot/src/main/resources/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/docker-compose.yml b/FP/docker-compose.yml
new file mode 100644
index 0000000..4195e6e
--- /dev/null
+++ b/FP/docker-compose.yml
@@ -0,0 +1,54 @@
+version: '1.-'
+
+services:
+ postgres:
+ container_name: postgres
+ image: postgres:15.2
+ environment:
+ POSTGRES_DB: postgres
+ POSTGRES_USER: scrap_user
+ POSTGRES_PASSWORD: hard_password
+ volumes:
+ - ./migrations/postgres_data:/var/lib/postgresql/data
+ ports:
+ - "5432:5432"
+ networks:
+ - backend
+
+ liquibase-migrations:
+ container_name: liquibase
+ image: liquibase/liquibase:4.18
+ 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://postgres:5432/postgres
+ - --username=scrap_user
+ - --password=hard_password
+ - --logLevel=debug
+ - update
+ volumes:
+ - ./migrations:/liquibase/changelog
+ networks:
+ - backend
+
+ rabbitmq:
+ image: rabbitmq:3-management-alpine
+ container_name: rabbitmq
+ ports:
+ - 5672:5672 # ΠΠΎΡΡ Π΄Π»Ρ AMQP
+ - 15672:15672 # ΠΠΎΡΡ Π΄Π»Ρ RabbitMQ Management UI
+ volumes:
+ - ./rabbitmq:/var/lib/rabbitmq
+ environment:
+ - RABBITMQ_DEFAULT_USER=guest
+ - RABBITMQ_DEFAULT_PASS=guest
+
+networks:
+ backend:
+ driver: bridge
\ No newline at end of file
diff --git a/FP/link-parser/pom.xml b/FP/link-parser/pom.xml
new file mode 100644
index 0000000..088df38
--- /dev/null
+++ b/FP/link-parser/pom.xml
@@ -0,0 +1,26 @@
+
+
+
+ org.example
+ FP
+ 1.0
+
+
+ 4.0.0
+
+ link-parser
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.2
+
+
+
\ 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
new file mode 100644
index 0000000..7bd8349
--- /dev/null
+++ b/FP/link-parser/src/test/java/LinkParserTest.java
@@ -0,0 +1,24 @@
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import ru.tinkoff.edu.java.linkparser.LinkParser;
+
+public class LinkParserTest {
+
+ 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
+ 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);
+ }
+}
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/FP/migrations/master.xml b/FP/migrations/master.xml
similarity index 83%
rename from FP/FP/migrations/master.xml
rename to FP/migrations/master.xml
index c566afc..5d643de 100644
--- a/FP/FP/migrations/master.xml
+++ b/FP/migrations/master.xml
@@ -7,7 +7,5 @@
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
-
-
-
+
\ No newline at end of file
diff --git a/FP/FP/pom.xml b/FP/pom.xml
similarity index 65%
rename from FP/FP/pom.xml
rename to FP/pom.xml
index a1baa3d..e38a124 100644
--- a/FP/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/FP/scrapper/pom.xml b/FP/scrapper/pom.xml
similarity index 69%
rename from FP/FP/scrapper/pom.xml
rename to FP/scrapper/pom.xml
index 1b0c4fa..fad5590 100644
--- a/FP/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,26 @@
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.testcontainers
junit-jupiter
test
-
- org.springframework.boot
- spring-boot-starter-test
-
org.testcontainers
postgresql
@@ -74,6 +86,7 @@
liquibase-core
test
+
org.springframework.boot
spring-boot-starter-jdbc
@@ -84,37 +97,20 @@
runtime
- org.jooq
- jooq
+ org.junit.jupiter
+ junit-jupiter
+ test
-
- org.springframework.boot
- spring-boot-starter-data-jpa
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.2
+
org.springframework.boot
spring-boot-starter-amqp
+ 3.0.6
-
-
-
-
- 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..0539e02
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java
@@ -0,0 +1,29 @@
+package ru.tinkoff.edu.java.scrapper;
+
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+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.configuration.ApplicationConfig;
+import ru.tinkoff.edu.java.scrapper.rabbitmq.ScrapperQueueProducer;
+import ru.tinkoff.edu.java.scrapper.rabbitmq.SendNoticeServiceQueue;
+
+@SpringBootApplication
+@EnableConfigurationProperties(ApplicationConfig.class)
+@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
+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("----------------------------------------------------------------");
+// 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/api/ScrapperControllerLinks.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerLinks.java
new file mode 100644
index 0000000..47540df
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerLinks.java
@@ -0,0 +1,46 @@
+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.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;
+
+@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/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/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/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
new file mode 100644
index 0000000..52af096
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java
@@ -0,0 +1,37 @@
+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;
+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
+@ConfigurationProperties(prefix = "app", ignoreUnknownFields = false)
+@EnableScheduling
+public record ApplicationConfig(
+ @NotNull String test,
+ @NotNull Scheduler scheduler,
+ Boolean useQueue,
+ String exchange,
+ String routingKey,
+ String queue
+) {
+@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
new file mode 100644
index 0000000..8682387
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java
@@ -0,0 +1,71 @@
+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.scrapper.model.LinkUpdate;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Configuration
+public class RabbitMQConfiguration {
+
+ private final ApplicationConfig config;
+
+ public RabbitMQConfiguration(ApplicationConfig config) {
+ this.config = config;
+ }
+
+ @Bean
+ public DirectExchange exchange() {
+ return new DirectExchange(config.exchange());
+ }
+
+ @Bean
+ public Queue 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());
+ }
+
+ @Bean
+ 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("localhost", 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/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..2d62856
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java
@@ -0,0 +1,81 @@
+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;
+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;
+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());
+ 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.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<>();
+ 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("Π£ Π²Π°Ρ Π½Π΅Ρ ΡΡΡΠ»ΠΎΠΊ");
+ }
+
+ }
+
+}
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..74a1fbe
--- /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/postgres");
+ 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..026139a
--- /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.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..4b52ef9
--- /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.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..914d113
--- /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.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..e40b248
--- /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.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..dfdbe71
--- /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.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;
+import java.util.Arrays;
+import java.util.List;
+
+public interface LinkOperations {
+ default void i_addLink(
+ JdbcTemplate jdbcTemplate,
+ String link
+ ) {
+ 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, link);
+ }
+
+ default void i_removeLink(
+ JdbcTemplate jdbcTemplate,
+ String link
+ ){
+ String query = "DELETE FROM links where link IN ('%s')";
+ query = query.formatted(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/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/model/ChatResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/ChatResponse.java
new file mode 100644
index 0000000..d1e1893
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/ChatResponse.java
@@ -0,0 +1,3 @@
+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/model/LinkChatResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkChatResponse.java
new file mode 100644
index 0000000..6ef6a2c
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkChatResponse.java
@@ -0,0 +1,3 @@
+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/model/LinkResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkResponse.java
new file mode 100644
index 0000000..d5192ab
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkResponse.java
@@ -0,0 +1,3 @@
+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/model/ListLinksResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/ListLinksResponse.java
new file mode 100644
index 0000000..6a04698
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/ListLinksResponse.java
@@ -0,0 +1,6 @@
+package ru.tinkoff.edu.java.scrapper.model;
+
+import java.util.*;
+
+public record ListLinksResponse(List links, int size) {}
+
diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/RemoveLinkRequest.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/RemoveLinkRequest.java
new file mode 100644
index 0000000..1f9b6ee
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/RemoveLinkRequest.java
@@ -0,0 +1,3 @@
+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
new file mode 100644
index 0000000..c592025
--- /dev/null
+++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java
@@ -0,0 +1,28 @@
+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.scrapper.configuration.ApplicationConfig;
+import ru.tinkoff.edu.java.scrapper.model.LinkUpdate;
+
+@Service
+
+public class ScrapperQueueProducer {
+ private final RabbitTemplate rabbitTemplate;
+
+ private final ApplicationConfig config;
+
+ public ScrapperQueueProducer(RabbitTemplate rabbitTemplate, ApplicationConfig config) {
+ this.rabbitTemplate = rabbitTemplate;
+ this.config = config;
+ }
+
+ public void send(LinkUpdate update) {
+ String exchange = config.exchange(); // ΠΠΌΡ ΠΎΠ±ΠΌΠ΅Π½Π°
+ String routingKey = config.routingKey(); // ΠΠ°ΡΡΡΡΡΠ½ΡΠΉ ΠΊΠ»ΡΡ
+
+ rabbitTemplate.convertAndSend(exchange, routingKey, update.url());
+ }
+}
+
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..70eed14
--- /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.scrapper.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/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..63acc43
--- /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/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
similarity index 62%
rename from FP/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java
rename to FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java
index 623f12b..d060c22 100644
--- a/FP/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/resources/application.properties b/FP/scrapper/src/main/resources/application.properties
new file mode 100644
index 0000000..d4267e9
--- /dev/null
+++ b/FP/scrapper/src/main/resources/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/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/README.md b/README.md
new file mode 100644
index 0000000..e69de29
From 2ee103a8f3748732626d785ca18c8026c2605044 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Fri, 19 May 2023 19:37:08 +0500
Subject: [PATCH 05/61] =?UTF-8?q?Workflows=20=D0=BF=D1=80=D0=B8=D0=B2?=
=?UTF-8?q?=D0=B5=D1=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/bot.yml | 23 +++++++++++++++++++++++
.github/workflows/scrapper.yml | 23 +++++++++++++++++++++++
2 files changed, 46 insertions(+)
create mode 100644 .github/workflows/bot.yml
create mode 100644 .github/workflows/scrapper.yml
diff --git a/.github/workflows/bot.yml b/.github/workflows/bot.yml
new file mode 100644
index 0000000..50833d9
--- /dev/null
+++ b/.github/workflows/bot.yml
@@ -0,0 +1,23 @@
+name: Bot Build
+
+on:
+ push:
+ paths:
+ - 'bot/**'
+
+jobs:
+ build:
+ name: Build Bot
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v2
+
+ - name: Set up JDK
+ uses: actions/setup-java@v2
+ with:
+ java-version: '11'
+
+ - name: Build Bot Application
+ run: mvn package -pl bot -am
\ No newline at end of file
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
new file mode 100644
index 0000000..bb83328
--- /dev/null
+++ b/.github/workflows/scrapper.yml
@@ -0,0 +1,23 @@
+name: Scrapper Build
+
+on:
+ push:
+ paths:
+ - 'scrapper/**'
+
+jobs:
+ build:
+ name: Build Scrapper
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v2
+
+ - name: Set up JDK
+ uses: actions/setup-java@v2
+ with:
+ java-version: '11'
+
+ - name: Build Scrapper Application
+ run: mvn package -pl scrapper -am
\ No newline at end of file
From cc8a642c82d6c956802a9ac486e2a975802e1387 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Fri, 19 May 2023 19:39:52 +0500
Subject: [PATCH 06/61] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD?=
=?UTF-8?q?=D0=B8=D0=B5=20=D0=BB=D0=B5=D0=B2=D0=BE=D0=B3=D0=BE=20=D1=82?=
=?UTF-8?q?=D0=B5=D1=81=D1=82=D0=B0,=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5?=
=?UTF-8?q?=D1=80=D0=BA=D0=B0=20workflows?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
FP/scrapper/src/test/java/JdbcAddTest.java | 9 ---------
1 file changed, 9 deletions(-)
delete mode 100644 FP/scrapper/src/test/java/JdbcAddTest.java
diff --git a/FP/scrapper/src/test/java/JdbcAddTest.java b/FP/scrapper/src/test/java/JdbcAddTest.java
deleted file mode 100644
index d5de9ec..0000000
--- a/FP/scrapper/src/test/java/JdbcAddTest.java
+++ /dev/null
@@ -1,9 +0,0 @@
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-class JdbcAddTest extends IntegrationEnvironment {
- @Test
- void create_test() {
-// Postgre_container.
- }
-}
From fe33f8a9a817a8b160f254cccf7e4e6835706427 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Fri, 19 May 2023 19:43:41 +0500
Subject: [PATCH 07/61] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?=
=?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BF=D1=83=D1=82=D0=B8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/bot.yml | 2 +-
.github/workflows/scrapper.yml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/bot.yml b/.github/workflows/bot.yml
index 50833d9..cd972f8 100644
--- a/.github/workflows/bot.yml
+++ b/.github/workflows/bot.yml
@@ -3,7 +3,7 @@ name: Bot Build
on:
push:
paths:
- - 'bot/**'
+ - 'FP/bot/**'
jobs:
build:
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index bb83328..fc61f38 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -3,7 +3,7 @@ name: Scrapper Build
on:
push:
paths:
- - 'scrapper/**'
+ - 'FP/scrapper/**'
jobs:
build:
From b20a4d839d3b6adccefca066f21385aa63f02b39 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Fri, 19 May 2023 19:47:19 +0500
Subject: [PATCH 08/61] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=BD=D0=BE?=
=?UTF-8?q?=D1=81=20workflows?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
FP/.github/workflows/bot.yml | 23 +++++++++++++++++++++++
FP/.github/workflows/scrapper.yml | 23 +++++++++++++++++++++++
2 files changed, 46 insertions(+)
create mode 100644 FP/.github/workflows/bot.yml
create mode 100644 FP/.github/workflows/scrapper.yml
diff --git a/FP/.github/workflows/bot.yml b/FP/.github/workflows/bot.yml
new file mode 100644
index 0000000..50833d9
--- /dev/null
+++ b/FP/.github/workflows/bot.yml
@@ -0,0 +1,23 @@
+name: Bot Build
+
+on:
+ push:
+ paths:
+ - 'bot/**'
+
+jobs:
+ build:
+ name: Build Bot
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v2
+
+ - name: Set up JDK
+ uses: actions/setup-java@v2
+ with:
+ java-version: '11'
+
+ - name: Build Bot Application
+ run: mvn package -pl bot -am
\ No newline at end of file
diff --git a/FP/.github/workflows/scrapper.yml b/FP/.github/workflows/scrapper.yml
new file mode 100644
index 0000000..bb83328
--- /dev/null
+++ b/FP/.github/workflows/scrapper.yml
@@ -0,0 +1,23 @@
+name: Scrapper Build
+
+on:
+ push:
+ paths:
+ - 'scrapper/**'
+
+jobs:
+ build:
+ name: Build Scrapper
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v2
+
+ - name: Set up JDK
+ uses: actions/setup-java@v2
+ with:
+ java-version: '11'
+
+ - name: Build Scrapper Application
+ run: mvn package -pl scrapper -am
\ No newline at end of file
From bf15ea7b2f84a833046a84c1c90f67a4e0c14d6b Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Fri, 19 May 2023 19:48:30 +0500
Subject: [PATCH 09/61] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD?=
=?UTF-8?q?=D0=B8=D0=B5=20=D1=81=D1=82=D0=B0=D1=80=D0=BE=D0=B3=D0=BE=20wor?=
=?UTF-8?q?kflows?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/bot.yml | 23 -----------------------
.github/workflows/scrapper.yml | 23 -----------------------
2 files changed, 46 deletions(-)
delete mode 100644 .github/workflows/bot.yml
delete mode 100644 .github/workflows/scrapper.yml
diff --git a/.github/workflows/bot.yml b/.github/workflows/bot.yml
deleted file mode 100644
index cd972f8..0000000
--- a/.github/workflows/bot.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-name: Bot Build
-
-on:
- push:
- paths:
- - 'FP/bot/**'
-
-jobs:
- build:
- name: Build Bot
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout Repository
- uses: actions/checkout@v2
-
- - name: Set up JDK
- uses: actions/setup-java@v2
- with:
- java-version: '11'
-
- - name: Build Bot Application
- run: mvn package -pl bot -am
\ No newline at end of file
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
deleted file mode 100644
index fc61f38..0000000
--- a/.github/workflows/scrapper.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-name: Scrapper Build
-
-on:
- push:
- paths:
- - 'FP/scrapper/**'
-
-jobs:
- build:
- name: Build Scrapper
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout Repository
- uses: actions/checkout@v2
-
- - name: Set up JDK
- uses: actions/setup-java@v2
- with:
- java-version: '11'
-
- - name: Build Scrapper Application
- run: mvn package -pl scrapper -am
\ No newline at end of file
From ab3cbb29f1b064e6ed4b8c7522d37f049495a03f Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Fri, 19 May 2023 20:07:10 +0500
Subject: [PATCH 10/61] =?UTF-8?q?=D0=97=D0=B0=D0=BC=D0=B5=D0=BD=D0=B0=20?=
=?UTF-8?q?=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D0=B8=3F=3F=3F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
FP/.github/workflows/bot.yml | 2 +-
FP/.github/workflows/scrapper.yml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/FP/.github/workflows/bot.yml b/FP/.github/workflows/bot.yml
index 50833d9..2fe7611 100644
--- a/FP/.github/workflows/bot.yml
+++ b/FP/.github/workflows/bot.yml
@@ -17,7 +17,7 @@ jobs:
- name: Set up JDK
uses: actions/setup-java@v2
with:
- java-version: '11'
+ java-version: '20'
- name: Build Bot Application
run: mvn package -pl bot -am
\ No newline at end of file
diff --git a/FP/.github/workflows/scrapper.yml b/FP/.github/workflows/scrapper.yml
index bb83328..4a19103 100644
--- a/FP/.github/workflows/scrapper.yml
+++ b/FP/.github/workflows/scrapper.yml
@@ -17,7 +17,7 @@ jobs:
- name: Set up JDK
uses: actions/setup-java@v2
with:
- java-version: '11'
+ java-version: '20'
- name: Build Scrapper Application
run: mvn package -pl scrapper -am
\ No newline at end of file
From 69d7e320b683ed5b209405464d5168a9c71a2a09 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Fri, 19 May 2023 22:02:32 +0500
Subject: [PATCH 11/61] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=BD=D0=BE?=
=?UTF-8?q?=D1=81=20workflows?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
{FP/.github => .github}/workflows/bot.yml | 0
.../workflows/scrapper.yml | 0
FP/bot/Dockerfile | 29 +++++++++++++++++++
FP/scrapper/Dockerfile | 4 +++
FP/scrapper/pom.xml | 1 +
5 files changed, 34 insertions(+)
rename {FP/.github => .github}/workflows/bot.yml (100%)
rename {FP/.github => .github}/workflows/scrapper.yml (100%)
create mode 100644 FP/bot/Dockerfile
create mode 100644 FP/scrapper/Dockerfile
diff --git a/FP/.github/workflows/bot.yml b/.github/workflows/bot.yml
similarity index 100%
rename from FP/.github/workflows/bot.yml
rename to .github/workflows/bot.yml
diff --git a/FP/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
similarity index 100%
rename from FP/.github/workflows/scrapper.yml
rename to .github/workflows/scrapper.yml
diff --git a/FP/bot/Dockerfile b/FP/bot/Dockerfile
new file mode 100644
index 0000000..9a6d58b
--- /dev/null
+++ b/FP/bot/Dockerfile
@@ -0,0 +1,29 @@
+# ΠΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ Π±Π°Π·ΠΎΠ²ΡΠΉ ΠΎΠ±ΡΠ°Π· Ρ ΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½Π½ΡΠΌ Java ΠΈ Maven
+FROM maven:3.8.4-openjdk-11 AS builder
+
+# Π£ΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΠΌ ΡΠ°Π±ΠΎΡΡΡ Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΡ Π² ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠ΅
+WORKDIR /app
+
+# ΠΠΎΠΏΠΈΡΡΠ΅ΠΌ ΡΠ°ΠΉΠ»Ρ Maven ΠΏΡΠΎΠ΅ΠΊΡΠ°
+COPY pom.xml .
+
+# Π‘ΠΊΠ°ΡΠΈΠ²Π°Π΅ΠΌ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΏΡΠΎΠ΅ΠΊΡΠ°
+RUN mvn dependency:go-offline -B
+
+# ΠΠΎΠΏΠΈΡΡΠ΅ΠΌ ΠΈΡΡ
ΠΎΠ΄Π½ΡΠΉ ΠΊΠΎΠ΄
+COPY src ./src
+
+# Π‘ΠΎΠ±ΠΈΡΠ°Π΅ΠΌ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅
+RUN mvn package -DskipTests
+
+# Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΠΊΠΎΠ½Π΅ΡΠ½ΡΠΉ Docker-ΠΎΠ±ΡΠ°Π·
+FROM openjdk:11-jre-slim
+
+# Π£ΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΠΌ ΡΠ°Π±ΠΎΡΡΡ Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΡ Π² ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠ΅
+WORKDIR /app
+
+# ΠΠΎΠΏΠΈΡΡΠ΅ΠΌ JAR ΡΠ°ΠΉΠ» ΠΈΠ· ΠΎΠ±ΡΠ°Π·Π° builder
+COPY --from=builder /app/target/bot.jar .
+
+# Π£ΠΊΠ°Π·ΡΠ²Π°Π΅ΠΌ ΠΊΠΎΠΌΠ°Π½Π΄Ρ Π΄Π»Ρ Π·Π°ΠΏΡΡΠΊΠ° Π±ΠΎΡΠ°
+CMD ["java", "-jar", "bot.jar"]
\ No newline at end of file
diff --git a/FP/scrapper/Dockerfile b/FP/scrapper/Dockerfile
new file mode 100644
index 0000000..6e556d3
--- /dev/null
+++ b/FP/scrapper/Dockerfile
@@ -0,0 +1,4 @@
+FROM openjdk:20
+WORKDIR /app/scrapper
+COPY target/scrapper-1.0.jar scrapper.jar
+ENTRYPOINT ["java", "-jar", "scrapper.jar"]
\ No newline at end of file
diff --git a/FP/scrapper/pom.xml b/FP/scrapper/pom.xml
index fad5590..30db9a3 100644
--- a/FP/scrapper/pom.xml
+++ b/FP/scrapper/pom.xml
@@ -113,4 +113,5 @@
3.0.6
+
\ No newline at end of file
From 2aa74c987a2867161632bce3ca045b30a987c1bb Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Fri, 19 May 2023 22:05:39 +0500
Subject: [PATCH 12/61] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?=
=?UTF-8?q?=D0=BD=D0=B8=D0=B5=20workflows?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/bot.yml | 2 +-
.github/workflows/scrapper.yml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/bot.yml b/.github/workflows/bot.yml
index 2fe7611..f718a7b 100644
--- a/.github/workflows/bot.yml
+++ b/.github/workflows/bot.yml
@@ -3,7 +3,7 @@ name: Bot Build
on:
push:
paths:
- - 'bot/**'
+ - 'FP/bot/**'
jobs:
build:
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index 4a19103..f929d2a 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -3,7 +3,7 @@ name: Scrapper Build
on:
push:
paths:
- - 'scrapper/**'
+ - 'FP/scrapper/**'
jobs:
build:
From da303ece0fef7446825e805a701ef64a323a9caf Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Fri, 19 May 2023 23:26:30 +0500
Subject: [PATCH 13/61] =?UTF-8?q?=D0=A1=D0=B5=D0=BA=D1=80=D0=B5=D1=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/bot.yml | 49 ++++++++++++++-----
FP/bot/Dockerfile | 31 ++----------
FP/bot/pom.xml | 25 ++++++++++
FP/pom.xml | 15 +-----
FP/scrapper/Dockerfile | 2 +-
FP/scrapper/pom.xml | 24 +++++++++
.../java/scrapper/ScrapperApplication.java | 2 +-
7 files changed, 94 insertions(+), 54 deletions(-)
diff --git a/.github/workflows/bot.yml b/.github/workflows/bot.yml
index f718a7b..4832485 100644
--- a/.github/workflows/bot.yml
+++ b/.github/workflows/bot.yml
@@ -1,23 +1,50 @@
-name: Bot Build
+name: Bot CI
on:
push:
paths:
- - 'FP/bot/**'
+ - "TinkoffEdu/bot/**"
+ - "TinkoffEdu/bot.Dockerfile"
+ - "TinkoffEdu/checkstyle.xml"
+ - "TinkoffEdu/pom.xml"
+ - ".github/workflows/bot.yaml"
jobs:
build:
- name: Build Bot
runs-on: ubuntu-latest
-
+ permissions:
+ contents: read
+ packages: write
steps:
- - name: Checkout Repository
- uses: actions/checkout@v2
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Set up JDK 19
+ uses: actions/setup-java@v3
+ with:
+ java-version: '19'
+ distribution: 'temurin'
+ cache: maven
+
+ - name: Build Maven project
+ run: mvn package -pl bot -am
- - name: Set up JDK
- uses: actions/setup-java@v2
+ - name: Login to GitHub Container Registry
+ uses: docker/login-action@v1
with:
- java-version: '20'
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.JAVAGUAVA }}
+
+ - name: Lowercase repo name
+ uses: actions/github-script@v6
+ id: lowercase_repo
+ with:
+ result-encoding: string
+ script: return 'ghcr.io/${{ github.repository }}'.toLowerCase()
+
+ - name: Build Docker image
+ run: docker build --file bot.Dockerfile -t ${{ steps.lowercase_repo.outputs.result }}/bot:latest .
- - name: Build Bot Application
- run: mvn package -pl bot -am
\ No newline at end of file
+ - name: Push Docker image to GitHub Container Registry
+ run: docker push ${{ steps.lowercase_repo.outputs.result }}/bot:latest
\ No newline at end of file
diff --git a/FP/bot/Dockerfile b/FP/bot/Dockerfile
index 9a6d58b..f9b97e1 100644
--- a/FP/bot/Dockerfile
+++ b/FP/bot/Dockerfile
@@ -1,29 +1,4 @@
-# ΠΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ Π±Π°Π·ΠΎΠ²ΡΠΉ ΠΎΠ±ΡΠ°Π· Ρ ΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½Π½ΡΠΌ Java ΠΈ Maven
-FROM maven:3.8.4-openjdk-11 AS builder
-
-# Π£ΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΠΌ ΡΠ°Π±ΠΎΡΡΡ Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΡ Π² ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠ΅
-WORKDIR /app
-
-# ΠΠΎΠΏΠΈΡΡΠ΅ΠΌ ΡΠ°ΠΉΠ»Ρ Maven ΠΏΡΠΎΠ΅ΠΊΡΠ°
-COPY pom.xml .
-
-# Π‘ΠΊΠ°ΡΠΈΠ²Π°Π΅ΠΌ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΏΡΠΎΠ΅ΠΊΡΠ°
-RUN mvn dependency:go-offline -B
-
-# ΠΠΎΠΏΠΈΡΡΠ΅ΠΌ ΠΈΡΡ
ΠΎΠ΄Π½ΡΠΉ ΠΊΠΎΠ΄
-COPY src ./src
-
-# Π‘ΠΎΠ±ΠΈΡΠ°Π΅ΠΌ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅
-RUN mvn package -DskipTests
-
-# Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΠΊΠΎΠ½Π΅ΡΠ½ΡΠΉ Docker-ΠΎΠ±ΡΠ°Π·
-FROM openjdk:11-jre-slim
-
-# Π£ΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΠΌ ΡΠ°Π±ΠΎΡΡΡ Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΡ Π² ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠ΅
-WORKDIR /app
-
-# ΠΠΎΠΏΠΈΡΡΠ΅ΠΌ JAR ΡΠ°ΠΉΠ» ΠΈΠ· ΠΎΠ±ΡΠ°Π·Π° builder
-COPY --from=builder /app/target/bot.jar .
-
-# Π£ΠΊΠ°Π·ΡΠ²Π°Π΅ΠΌ ΠΊΠΎΠΌΠ°Π½Π΄Ρ Π΄Π»Ρ Π·Π°ΠΏΡΡΠΊΠ° Π±ΠΎΡΠ°
+FROM openjdk:20
+WORKDIR /app/bot
+COPY target/bot-1.0.jar bot.jar
CMD ["java", "-jar", "bot.jar"]
\ No newline at end of file
diff --git a/FP/bot/pom.xml b/FP/bot/pom.xml
index 96dea0d..58ec92a 100644
--- a/FP/bot/pom.xml
+++ b/FP/bot/pom.xml
@@ -107,4 +107,29 @@
compile
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ maven-compiler-plugin
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+ 2.22.2
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.2
+
+
+
\ No newline at end of file
diff --git a/FP/pom.xml b/FP/pom.xml
index e38a124..73212ce 100644
--- a/FP/pom.xml
+++ b/FP/pom.xml
@@ -33,22 +33,10 @@
-
- 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
@@ -69,6 +57,7 @@
+
org.apache.maven.plugins
maven-compiler-plugin
diff --git a/FP/scrapper/Dockerfile b/FP/scrapper/Dockerfile
index 6e556d3..453a446 100644
--- a/FP/scrapper/Dockerfile
+++ b/FP/scrapper/Dockerfile
@@ -1,4 +1,4 @@
FROM openjdk:20
WORKDIR /app/scrapper
COPY target/scrapper-1.0.jar scrapper.jar
-ENTRYPOINT ["java", "-jar", "scrapper.jar"]
\ No newline at end of file
+CMD ["java", "-jar", "scrapper.jar"]
\ No newline at end of file
diff --git a/FP/scrapper/pom.xml b/FP/scrapper/pom.xml
index 30db9a3..62e2b12 100644
--- a/FP/scrapper/pom.xml
+++ b/FP/scrapper/pom.xml
@@ -113,5 +113,29 @@
3.0.6
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ maven-compiler-plugin
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+ 2.22.2
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.2
+
+
+
\ 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 0539e02..db3b685 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,6 @@ public static void main(String[] args) {
// config
// ));
// notificationService.sendNotice("ΠΠΎΡ-Π²ΠΎΡ");
-// Cannot invoke "org.springframework.amqp.rabbit.connection.ConnectionFactory.createConnection()" because "connectionFactory" is null
+//// Cannot invoke "org.springframework.amqp.rabbit.connection.ConnectionFactory.createConnection()" because "connectionFactory" is null
}
}
From fac3782b39a60a266b114896156c07498d594f09 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Fri, 19 May 2023 23:31:37 +0500
Subject: [PATCH 14/61] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?=
=?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=B2=20workflows?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/bot.yml | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/bot.yml b/.github/workflows/bot.yml
index 4832485..7fe6e8c 100644
--- a/.github/workflows/bot.yml
+++ b/.github/workflows/bot.yml
@@ -3,10 +3,8 @@ name: Bot CI
on:
push:
paths:
- - "TinkoffEdu/bot/**"
- - "TinkoffEdu/bot.Dockerfile"
- - "TinkoffEdu/checkstyle.xml"
- - "TinkoffEdu/pom.xml"
+ - "FP/bot/**"
+ - "FP/pom.xml"
- ".github/workflows/bot.yaml"
jobs:
From 5b9aa500773ba80074320d0d5582df5ac64579e9 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Fri, 19 May 2023 23:34:04 +0500
Subject: [PATCH 15/61] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?=
=?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20workflows=20scrapper?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 47 ++++++++++++++++++++++++++--------
1 file changed, 36 insertions(+), 11 deletions(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index f929d2a..7fa26f2 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -1,23 +1,48 @@
-name: Scrapper Build
+name: Scrapper CI
on:
push:
paths:
- - 'FP/scrapper/**'
+ - "FP/bot/**"
+ - "FP/pom.xml"
+ - ".github/workflows/bot.yaml"
jobs:
build:
- name: Build Scrapper
runs-on: ubuntu-latest
-
+ permissions:
+ contents: read
+ packages: write
steps:
- - name: Checkout Repository
- uses: actions/checkout@v2
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Set up JDK 19
+ uses: actions/setup-java@v3
+ with:
+ java-version: '19'
+ distribution: 'temurin'
+ cache: maven
+
+ - name: Build Maven project
+ run: mvn package -pl bot -am
- - name: Set up JDK
- uses: actions/setup-java@v2
+ - name: Login to GitHub Container Registry
+ uses: docker/login-action@v1
with:
- java-version: '20'
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.JAVAGUAVA }}
+
+ - name: Lowercase repo name
+ uses: actions/github-script@v6
+ id: lowercase_repo
+ with:
+ result-encoding: string
+ script: return 'ghcr.io/${{ github.repository }}'.toLowerCase()
+
+ - name: Build Docker image
+ run: docker build --file bot.Dockerfile -t ${{ steps.lowercase_repo.outputs.result }}/bot:latest .
- - name: Build Scrapper Application
- run: mvn package -pl scrapper -am
\ No newline at end of file
+ - name: Push Docker image to GitHub Container Registry
+ run: docker push ${{ steps.lowercase_repo.outputs.result }}/bot:latest
\ No newline at end of file
From 9ce98090003e2e7bfd48b3a31cc4b561fc8d201a Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 01:48:05 +0500
Subject: [PATCH 16/61] =?UTF-8?q?=D0=A3=D0=B1=D1=80=D0=B0=D0=BD=D1=8B=20?=
=?UTF-8?q?=D0=BB=D0=B8=D1=88=D0=BD=D0=B8=D0=B5=20=D0=B8=D0=BC=D0=BF=D0=BE?=
=?UTF-8?q?=D1=80=D1=82=D1=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
FP/bot/pom.xml | 11 +++--
.../ru/tinkoff/edu/java/bot/handler/DB.java | 42 -------------------
.../edu/java/bot/handler/commands/List.java | 4 --
.../edu/java/bot/handler/commands/Start.java | 1 -
.../edu/java/bot/handler/commands/Track.java | 6 ---
.../java/bot/handler/commands/Untrack.java | 1 -
6 files changed, 5 insertions(+), 60 deletions(-)
delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/DB.java
diff --git a/FP/bot/pom.xml b/FP/bot/pom.xml
index 58ec92a..7825351 100644
--- a/FP/bot/pom.xml
+++ b/FP/bot/pom.xml
@@ -18,6 +18,11 @@
+
+ org.example
+ scrapper
+ 1.0
+
org.springdoc
@@ -100,12 +105,6 @@
postgresql
runtime
-
- org.example
- scrapper
- 1.0
- compile
-
diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/DB.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/DB.java
deleted file mode 100644
index 6b57338..0000000
--- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/DB.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package ru.tinkoff.edu.java.bot.handler;
-
-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/handler/commands/List.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/List.java
index 280f80a..4d21022 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,11 +1,7 @@
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;
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 d2d5459..052a171 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,7 +1,6 @@
package ru.tinkoff.edu.java.bot.handler.commands;
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 {
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 9080b48..f0bfd43 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
@@ -2,17 +2,11 @@
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 extends LinkOperations, LinkChatOperations, ChatOperations {
default String track(JdbcTemplate jdbc, String link, long chat) {
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 6615feb..30aafae 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,7 +1,6 @@
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;
From c5b88b50fc9bb8844f9dde1ee330844a987ac1dc Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 02:58:58 +0500
Subject: [PATCH 17/61] =?UTF-8?q?=D0=9F=D1=80=D0=BE=D0=B1=D0=BB=D0=B5?=
=?UTF-8?q?=D0=BC=D0=B0=20=D1=81=20package=20bot=20=D0=BD=D0=B5=20=D1=80?=
=?UTF-8?q?=D0=B5=D1=88=D0=B5=D0=BD=D0=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/bot.yml | 48 ----------------
.github/workflows/scrapper.yml | 50 +++++-----------
FP/bot/pom.xml | 11 ++--
FP/link-parser/pom.xml | 55 ++++++++++++++++--
FP/pom.xml | 101 ++++++++++++++++-----------------
FP/scrapper/pom.xml | 84 +++++++++++++++------------
6 files changed, 168 insertions(+), 181 deletions(-)
delete mode 100644 .github/workflows/bot.yml
diff --git a/.github/workflows/bot.yml b/.github/workflows/bot.yml
deleted file mode 100644
index 7fe6e8c..0000000
--- a/.github/workflows/bot.yml
+++ /dev/null
@@ -1,48 +0,0 @@
-name: Bot CI
-
-on:
- push:
- paths:
- - "FP/bot/**"
- - "FP/pom.xml"
- - ".github/workflows/bot.yaml"
-
-jobs:
- build:
- runs-on: ubuntu-latest
- permissions:
- contents: read
- packages: write
- steps:
- - name: Checkout
- uses: actions/checkout@v3
-
- - name: Set up JDK 19
- uses: actions/setup-java@v3
- with:
- java-version: '19'
- distribution: 'temurin'
- cache: maven
-
- - name: Build Maven project
- run: mvn package -pl bot -am
-
- - name: Login to GitHub Container Registry
- uses: docker/login-action@v1
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ secrets.JAVAGUAVA }}
-
- - name: Lowercase repo name
- uses: actions/github-script@v6
- id: lowercase_repo
- with:
- result-encoding: string
- script: return 'ghcr.io/${{ github.repository }}'.toLowerCase()
-
- - name: Build Docker image
- run: docker build --file bot.Dockerfile -t ${{ steps.lowercase_repo.outputs.result }}/bot:latest .
-
- - name: Push Docker image to GitHub Container Registry
- run: docker push ${{ steps.lowercase_repo.outputs.result }}/bot:latest
\ No newline at end of file
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index 7fa26f2..b1b6769 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -1,48 +1,26 @@
-name: Scrapper CI
+name: Scrapper Build
on:
push:
paths:
- - "FP/bot/**"
- - "FP/pom.xml"
- - ".github/workflows/bot.yaml"
+ - '.FP/scrapper/**'
+ pull_request:
+ paths:
+ - '.FP/scrapper/**'
+ - '.github/workflows/scrapper.yml' # Include this path to trigger the workflow when changes are made to the workflow file itself
jobs:
build:
runs-on: ubuntu-latest
- permissions:
- contents: read
- packages: write
- steps:
- - name: Checkout
- uses: actions/checkout@v3
-
- - name: Set up JDK 19
- uses: actions/setup-java@v3
- with:
- java-version: '19'
- distribution: 'temurin'
- cache: maven
- - name: Build Maven project
- run: mvn package -pl bot -am
-
- - name: Login to GitHub Container Registry
- uses: docker/login-action@v1
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ secrets.JAVAGUAVA }}
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v2
- - name: Lowercase repo name
- uses: actions/github-script@v6
- id: lowercase_repo
+ - name: Set up JDK 20
+ uses: actions/setup-java@v2
with:
- result-encoding: string
- script: return 'ghcr.io/${{ github.repository }}'.toLowerCase()
-
- - name: Build Docker image
- run: docker build --file bot.Dockerfile -t ${{ steps.lowercase_repo.outputs.result }}/bot:latest .
+ java-version: 20
- - name: Push Docker image to GitHub Container Registry
- run: docker push ${{ steps.lowercase_repo.outputs.result }}/bot:latest
\ No newline at end of file
+ - name: Build and package scrapper
+ run: mvn package -pl scrapper -am
diff --git a/FP/bot/pom.xml b/FP/bot/pom.xml
index 7825351..58ec92a 100644
--- a/FP/bot/pom.xml
+++ b/FP/bot/pom.xml
@@ -18,11 +18,6 @@
-
- org.example
- scrapper
- 1.0
-
org.springdoc
@@ -105,6 +100,12 @@
postgresql
runtime
+
+ org.example
+ scrapper
+ 1.0
+ compile
+
diff --git a/FP/link-parser/pom.xml b/FP/link-parser/pom.xml
index 088df38..8de37c0 100644
--- a/FP/link-parser/pom.xml
+++ b/FP/link-parser/pom.xml
@@ -3,24 +3,71 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- org.example
FP
+ org.example
1.0
-
4.0.0
link-parser
+
+
+ 17
+ 17
+ 5.8.2
+ 4.5.1
+
+
org.junit.jupiter
- junit-jupiter
+ junit-jupiter-api
+ ${junit-jupiter.version}
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ ${junit-jupiter.version}
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ ${junit-jupiter.version}
test
org.apache.maven.plugins
maven-surefire-plugin
- 2.22.2
+ 3.0.0
+ maven-plugin
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+ 2.22.2
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.2
+
+
+
+
\ No newline at end of file
diff --git a/FP/pom.xml b/FP/pom.xml
index 73212ce..a023481 100644
--- a/FP/pom.xml
+++ b/FP/pom.xml
@@ -1,16 +1,22 @@
-
-
+
+
4.0.0
-
org.example
-
FP
-
+ 1.0
pom
- 1.0
+ FP
+
+
+ UTF-8
+ 19
+ 19
+ 2022.0.0
+ 3.0.1
+ 3.10.1
+ 1.17.6
+
bot
@@ -18,17 +24,42 @@
scrapper
-
- UTF-8
- 17
- 17
- 3.8.1
- 3.0.1
- 2022.0.0
- 23.1.0
- 5.8.1
- 1.18.0
-
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${spring-boot.version}
+ pom
+ import
+
+
+
+ org.testcontainers
+ testcontainers-bom
+ ${testcontainers.version}
+ pom
+ import
+
+
+
+
+
+
+ org.jetbrains
+ annotations
+ 23.1.0
+ provided
+
+
@@ -70,36 +101,4 @@
-
-
-
-
- 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/pom.xml b/FP/scrapper/pom.xml
index 62e2b12..e214fdf 100644
--- a/FP/scrapper/pom.xml
+++ b/FP/scrapper/pom.xml
@@ -1,118 +1,129 @@
-
+
+ 4.0.0
- org.example
FP
+ org.example
1.0
- 4.0.0
-
+ org.example
scrapper
+ 1.0
+
+ scrapper
- 3.0.1
- 2.7.6
+ UTF-8
+ 19
+ 19
-
-
- org.springdoc
- springdoc-openapi-starter-webmvc-ui
- 2.0.2
-
-
org.springframework.boot
- spring-boot-starter-validation
- ${starter-validation.version}
+ spring-boot-starter-web
+
org.springframework.boot
- spring-boot-starter-web
- ${starter-web.version}
+ spring-boot-starter-validation
+
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.example
- link-parser
- 1.0
- compile
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ 2.0.2
-
-
+
org.springframework.boot
spring-boot-starter-webflux
- 3.0.5
-
+
org.testcontainers
junit-jupiter
test
+
org.testcontainers
postgresql
test
+
org.liquibase
liquibase-core
test
-
+
org.springframework.boot
spring-boot-starter-jdbc
+
org.postgresql
postgresql
runtime
+
- org.junit.jupiter
- junit-jupiter
+ org.example
+ link-parser
+ 1.0
+ compile
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
test
+
- org.apache.maven.plugins
- maven-surefire-plugin
- 2.22.2
+ org.springframework.boot
+ spring-boot-starter-jooq
-
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
org.springframework.boot
spring-boot-starter-amqp
- 3.0.6
+
@@ -137,5 +148,4 @@
-
\ No newline at end of file
From 739b32f688b590e3763e0391ae006cccb8f7ea60 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:01:40 +0500
Subject: [PATCH 18/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=20=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=B8=D1=82=D1=8C?=
=?UTF-8?q?=20CI?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index b1b6769..c449766 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -17,10 +17,10 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v2
- - name: Set up JDK 20
+ - name: Set up JDK 11
uses: actions/setup-java@v2
with:
- java-version: 20
+ java-version: 11
- name: Build and package scrapper
run: mvn package -pl scrapper -am
From 702aa976f02bd816fecbe700ff038f9ba42d1ec0 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:09:53 +0500
Subject: [PATCH 19/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=20=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=B8=D1=82=D1=8C?=
=?UTF-8?q?=20CI2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index c449766..49c8a12 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -14,13 +14,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- - name: Checkout repository
- uses: actions/checkout@v2
-
- - name: Set up JDK 11
- uses: actions/setup-java@v2
- with:
- java-version: 11
-
- - name: Build and package scrapper
- run: mvn package -pl scrapper -am
+ - uses: actions/checkout@v3
+ - uses: actions/setup-java@v3
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+ - name: Run the Maven verify phase
+ run: mvn --batch-mode --update-snapshots verify
From 54d943b459ca1d59e13de694807d489df851d6cf Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:13:55 +0500
Subject: [PATCH 20/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=20=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=B8=D1=82=D1=8C?=
=?UTF-8?q?=20CI3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index 49c8a12..f16d6f0 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -18,6 +18,6 @@ jobs:
- uses: actions/setup-java@v3
with:
java-version: '17'
- distribution: 'temurin'
+ distribution: 'ubuntu-latest'
- name: Run the Maven verify phase
run: mvn --batch-mode --update-snapshots verify
From 5c63d1b2c6cf99a2d1b0be8e2f400b5f55b92834 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:16:33 +0500
Subject: [PATCH 21/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=20=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=B8=D1=82=D1=8C?=
=?UTF-8?q?=20CI4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index f16d6f0..bacb0da 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -12,12 +12,18 @@ on:
jobs:
build:
runs-on: ubuntu-latest
+ inputs:
+ distribution: ubuntu-lates
+ required: true
steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-java@v3
- with:
- java-version: '17'
- distribution: 'ubuntu-latest'
- - name: Run the Maven verify phase
- run: mvn --batch-mode --update-snapshots verify
+ - name: Checkout repository
+ uses: actions/checkout@v2
+
+ - name: Set up JDK 11
+ uses: actions/setup-java@v2
+ with:
+ java-version: 11
+
+ - name: Build and package scrapper
+ run: mvn package -pl scrapper -am
From 13e91a0dffd8c63688f272aed49b28ae24dfcb8d Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:18:10 +0500
Subject: [PATCH 22/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=20=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=B8=D1=82=D1=8C?=
=?UTF-8?q?=20CI5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 3 ---
1 file changed, 3 deletions(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index bacb0da..c449766 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -12,9 +12,6 @@ on:
jobs:
build:
runs-on: ubuntu-latest
- inputs:
- distribution: ubuntu-lates
- required: true
steps:
- name: Checkout repository
From d04960e9fc7dbfa69180f2152578f95a96b41fa2 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:20:33 +0500
Subject: [PATCH 23/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=20=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=B8=D1=82=D1=8C?=
=?UTF-8?q?=20CI6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index c449766..0b904c6 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -13,6 +13,11 @@ jobs:
build:
runs-on: ubuntu-latest
+ inputs:
+ distribution:
+ description: 'Distribution of the application'
+ required: true
+
steps:
- name: Checkout repository
uses: actions/checkout@v2
From a5762ced61cd05c44d2f51065357b371d87c02ae Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:22:41 +0500
Subject: [PATCH 24/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=20=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=B8=D1=82=D1=8C?=
=?UTF-8?q?=20CI7?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index 0b904c6..38d2f7c 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -13,10 +13,8 @@ jobs:
build:
runs-on: ubuntu-latest
- inputs:
- distribution:
- description: 'Distribution of the application'
- required: true
+ env:
+ DISTRIBUTION: ${{ github.event.inputs.distribution }}
steps:
- name: Checkout repository
@@ -28,4 +26,5 @@ jobs:
java-version: 11
- name: Build and package scrapper
- run: mvn package -pl scrapper -am
+ run: |
+ mvn package -pl scrapper -am
From 5788ba9ad9c2f571b579d5243d7f08a81696efaa Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:25:41 +0500
Subject: [PATCH 25/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=20=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=B8=D1=82=D1=8C?=
=?UTF-8?q?=20CI8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 33 +++++++++++++++------------------
1 file changed, 15 insertions(+), 18 deletions(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index 38d2f7c..ce6ee9c 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -1,30 +1,27 @@
-name: Scrapper Build
+name: Scrapper CI
on:
push:
paths:
- - '.FP/scrapper/**'
- pull_request:
- paths:
- - '.FP/scrapper/**'
- - '.github/workflows/scrapper.yml' # Include this path to trigger the workflow when changes are made to the workflow file itself
+ - ".FP/scrapper/**"
+ - ".github/workflows/scrapper.yaml"
jobs:
build:
runs-on: ubuntu-latest
-
- env:
- DISTRIBUTION: ${{ github.event.inputs.distribution }}
-
+ permissions:
+ contents: read
+ packages: write
steps:
- - name: Checkout repository
- uses: actions/checkout@v2
+ - name: Checkout
+ uses: actions/checkout@v3
- - name: Set up JDK 11
- uses: actions/setup-java@v2
+ - name: Set up JDK 19
+ uses: actions/setup-java@v3
with:
- java-version: 11
+ java-version: '19'
+ distribution: 'temurin'
+ cache: maven
- - name: Build and package scrapper
- run: |
- mvn package -pl scrapper -am
+ - name: Build Maven project
+ run: mvn package -pl scrapper -am
\ No newline at end of file
From 850428d76b6f4593ed5c3d1184d62037a98fc205 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:27:55 +0500
Subject: [PATCH 26/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=20=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=B8=D1=82=D1=8C?=
=?UTF-8?q?=20CI9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index ce6ee9c..a3776d1 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -1,4 +1,4 @@
-name: Scrapper CI
+name: Scrapper Build
on:
push:
From e40db0dbe6817a82bdde6c0d078f06be65fb22f6 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:30:34 +0500
Subject: [PATCH 27/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=2010?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
{.github => FP/.github}/workflows/scrapper.yml | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename {.github => FP/.github}/workflows/scrapper.yml (100%)
diff --git a/.github/workflows/scrapper.yml b/FP/.github/workflows/scrapper.yml
similarity index 100%
rename from .github/workflows/scrapper.yml
rename to FP/.github/workflows/scrapper.yml
From 4ae09b0afee6fd920d6ea9662e85f67948fe24e4 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:31:49 +0500
Subject: [PATCH 28/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=2011?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
FP/.github/workflows/scrapper.yml | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/FP/.github/workflows/scrapper.yml b/FP/.github/workflows/scrapper.yml
index a3776d1..0e7bf95 100644
--- a/FP/.github/workflows/scrapper.yml
+++ b/FP/.github/workflows/scrapper.yml
@@ -3,8 +3,7 @@ name: Scrapper Build
on:
push:
paths:
- - ".FP/scrapper/**"
- - ".github/workflows/scrapper.yaml"
+ - "FP/scrapper/**"
jobs:
build:
From d9d08aada5ffddc3a790d8e34e0603c2c832d84a Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:33:47 +0500
Subject: [PATCH 29/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=2011?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 30 ++++++++++++++++++++++++++++++
FP/.github/workflows/scrapper.yml | 26 --------------------------
2 files changed, 30 insertions(+), 26 deletions(-)
create mode 100644 .github/workflows/scrapper.yml
delete mode 100644 FP/.github/workflows/scrapper.yml
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
new file mode 100644
index 0000000..b0793f2
--- /dev/null
+++ b/.github/workflows/scrapper.yml
@@ -0,0 +1,30 @@
+name: Scrapper Build
+
+on:
+ push:
+ paths:
+ - '.FP/scrapper/**'
+ pull_request:
+ paths:
+ - '.FP/scrapper/**'
+ - '.github/workflows/scrapper.yml' # Include this path to trigger the workflow when changes are made to the workflow file itself
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ env:
+ DISTRIBUTION: ${{ github.event.inputs.distribution }}
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v2
+
+ - name: Set up JDK 11
+ uses: actions/setup-java@v2
+ with:
+ java-version: 11
+
+ - name: Build and package scrapper
+ run: |
+ mvn package -pl scrapper -am
\ No newline at end of file
diff --git a/FP/.github/workflows/scrapper.yml b/FP/.github/workflows/scrapper.yml
deleted file mode 100644
index 0e7bf95..0000000
--- a/FP/.github/workflows/scrapper.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-name: Scrapper Build
-
-on:
- push:
- paths:
- - "FP/scrapper/**"
-
-jobs:
- build:
- runs-on: ubuntu-latest
- permissions:
- contents: read
- packages: write
- steps:
- - name: Checkout
- uses: actions/checkout@v3
-
- - name: Set up JDK 19
- uses: actions/setup-java@v3
- with:
- java-version: '19'
- distribution: 'temurin'
- cache: maven
-
- - name: Build Maven project
- run: mvn package -pl scrapper -am
\ No newline at end of file
From 8d9f2510059ddb3f5784da300c1390c0972bbff0 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:36:35 +0500
Subject: [PATCH 30/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=2012?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index b0793f2..a7be867 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -13,17 +13,19 @@ jobs:
build:
runs-on: ubuntu-latest
- env:
- DISTRIBUTION: ${{ github.event.inputs.distribution }}
+ distribution:
+ description: 'Distribution of the application'
+ required: true
+ default: 'ubuntu-latest'
steps:
- name: Checkout repository
uses: actions/checkout@v2
- - name: Set up JDK 11
+ - name: Set up JDK 20
uses: actions/setup-java@v2
with:
- java-version: 11
+ java-version: 20
- name: Build and package scrapper
run: |
From c4dd3bc3cd02a178a8c6cfe3f2f0c2a0a8830906 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:39:45 +0500
Subject: [PATCH 31/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=2013?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 22 +++++++---------------
1 file changed, 7 insertions(+), 15 deletions(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index a7be867..e582ef9 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -13,20 +13,12 @@ jobs:
build:
runs-on: ubuntu-latest
- distribution:
- description: 'Distribution of the application'
- required: true
- default: 'ubuntu-latest'
-
steps:
- - name: Checkout repository
- uses: actions/checkout@v2
-
- - name: Set up JDK 20
- uses: actions/setup-java@v2
+ - uses: actions/checkout@v3
+ - name: Set up JDK 17
+ uses: actions/setup-java@v3
with:
- java-version: 20
-
- - name: Build and package scrapper
- run: |
- mvn package -pl scrapper -am
\ No newline at end of file
+ java-version: '17'
+ distribution: 'temurin'
+ - name: Build with Maven
+ run: mvn package
\ No newline at end of file
From 520022edf5d194cbfbff12f629b0ce709e74e8dd Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:41:43 +0500
Subject: [PATCH 32/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=2014?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index e582ef9..6250dd8 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -21,4 +21,4 @@ jobs:
java-version: '17'
distribution: 'temurin'
- name: Build with Maven
- run: mvn package
\ No newline at end of file
+ run: mvn package -pl scrapper -am
\ No newline at end of file
From 3a6bdd6718046d3e45ae04865d0e04cb6a201ae4 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:43:26 +0500
Subject: [PATCH 33/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=2015?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index 6250dd8..dd5c4ac 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -14,11 +14,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
+
- name: Build with Maven
- run: mvn package -pl scrapper -am
\ No newline at end of file
+ run: mvn package -pl scrapper -am
From dcc947f1f9104dfd06ab810fbb3b26214089f9ef Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:45:24 +0500
Subject: [PATCH 34/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=2016?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index dd5c4ac..2a3df2f 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -3,10 +3,10 @@ name: Scrapper Build
on:
push:
paths:
- - '.FP/scrapper/**'
+ - '../FP/scrapper/**'
pull_request:
paths:
- - '.FP/scrapper/**'
+ - '../FP/scrapper/**'
- '.github/workflows/scrapper.yml' # Include this path to trigger the workflow when changes are made to the workflow file itself
jobs:
From e58a31c16b8290a8d23880271077282f6580c8c2 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:48:10 +0500
Subject: [PATCH 35/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=2017?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index 2a3df2f..649a073 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -7,12 +7,14 @@ on:
pull_request:
paths:
- '../FP/scrapper/**'
- - '.github/workflows/scrapper.yml' # Include this path to trigger the workflow when changes are made to the workflow file itself
+ - '.github/workflows/scrapper.yml'
jobs:
build:
runs-on: ubuntu-latest
-
+ permissions:
+ contents: read
+ packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
From f24afe08e49aa3728be4c49728d97629fc95ab63 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:49:59 +0500
Subject: [PATCH 36/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=2018?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index 649a073..6d5079b 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -3,10 +3,10 @@ name: Scrapper Build
on:
push:
paths:
- - '../FP/scrapper/**'
+ - 'FP/scrapper/**'
pull_request:
paths:
- - '../FP/scrapper/**'
+ - 'FP/scrapper/**'
- '.github/workflows/scrapper.yml'
jobs:
@@ -19,10 +19,10 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v3
- - name: Set up JDK 17
+ - name: Set up JDK 20
uses: actions/setup-java@v3
with:
- java-version: '17'
+ java-version: '20'
distribution: 'temurin'
- name: Build with Maven
From 2a2c1cdb00f53da86a6029b27af7857cd44587ff Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:52:45 +0500
Subject: [PATCH 37/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=2019?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
{.github => FP/.github}/workflows/scrapper.yml | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename {.github => FP/.github}/workflows/scrapper.yml (100%)
diff --git a/.github/workflows/scrapper.yml b/FP/.github/workflows/scrapper.yml
similarity index 100%
rename from .github/workflows/scrapper.yml
rename to FP/.github/workflows/scrapper.yml
From 6c1901ec4f6b51e966a6f9b0b14f9ff5e373e4e4 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:54:05 +0500
Subject: [PATCH 38/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=2020?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
{FP/.github => .github}/workflows/scrapper.yml | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename {FP/.github => .github}/workflows/scrapper.yml (100%)
diff --git a/FP/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
similarity index 100%
rename from FP/.github/workflows/scrapper.yml
rename to .github/workflows/scrapper.yml
From 2ebb200bf930cb6d5d2a90efa6f80165955650c0 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 03:58:08 +0500
Subject: [PATCH 39/61] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?=
=?UTF-8?q?=D0=B0=2021?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index 6d5079b..f7c20b2 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -4,6 +4,7 @@ on:
push:
paths:
- 'FP/scrapper/**'
+ - 'FP/pom.xml'
pull_request:
paths:
- 'FP/scrapper/**'
@@ -24,6 +25,7 @@ jobs:
with:
java-version: '20'
distribution: 'temurin'
+ cache: maven
- name: Build with Maven
- run: mvn package -pl scrapper -am
+ run: cd FP && mvn package -pl scrapper -am
From 6d09d45be643f4a5a3acaeb563647c56e0bd2e61 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 04:01:43 +0500
Subject: [PATCH 40/61] =?UTF-8?q?=D0=97=D0=B0=D0=BF=D1=83=D1=81=D0=BA=20?=
=?UTF-8?q?=D0=BA=D0=BE=D0=BD=D1=82=D0=B5=D0=B9=D0=BD=D0=B5=D1=80=D0=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index f7c20b2..6012cf0 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -29,3 +29,7 @@ jobs:
- name: Build with Maven
run: cd FP && mvn package -pl scrapper -am
+
+
+ - name: Build scrapper Docker image
+ run: docker build -t scrapper-image -f Dockerfile .
From 9b3bc28e495a6bf18ba9efc2984fb04c32a0ad37 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 04:03:56 +0500
Subject: [PATCH 41/61] =?UTF-8?q?=D0=97=D0=B0=D0=BF=D1=83=D1=81=D0=BA=20?=
=?UTF-8?q?=D0=BA=D0=BE=D0=BD=D1=82=D0=B5=D0=B9=D0=BD=D0=B5=D1=80=D0=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index 6012cf0..222d5bf 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -32,4 +32,4 @@ jobs:
- name: Build scrapper Docker image
- run: docker build -t scrapper-image -f Dockerfile .
+ run: cd scrapper && docker build -t scrapper-image -f Dockerfile .
From 2442f91efa8e0f357ad19da9236b1ef9853ffdcf Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 04:06:11 +0500
Subject: [PATCH 42/61] =?UTF-8?q?=D0=97=D0=B0=D0=BF=D1=83=D1=81=D0=BA=20?=
=?UTF-8?q?=D0=BA=D0=BE=D0=BD=D1=82=D0=B5=D0=B9=D0=BD=D0=B5=D1=80=D0=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 2 +-
FP/{scrapper/Dockerfile => scrapper.Dockerfile} | 0
2 files changed, 1 insertion(+), 1 deletion(-)
rename FP/{scrapper/Dockerfile => scrapper.Dockerfile} (100%)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index 222d5bf..6012cf0 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -32,4 +32,4 @@ jobs:
- name: Build scrapper Docker image
- run: cd scrapper && docker build -t scrapper-image -f Dockerfile .
+ run: docker build -t scrapper-image -f Dockerfile .
diff --git a/FP/scrapper/Dockerfile b/FP/scrapper.Dockerfile
similarity index 100%
rename from FP/scrapper/Dockerfile
rename to FP/scrapper.Dockerfile
From d8ce43d94da34b78270cd9e38d38c334a65df8db Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 04:07:44 +0500
Subject: [PATCH 43/61] =?UTF-8?q?=D0=97=D0=B0=D0=BF=D1=83=D1=81=D0=BA=20?=
=?UTF-8?q?=D0=BA=D0=BE=D0=BD=D1=82=D0=B5=D0=B9=D0=BD=D0=B5=D1=80=D0=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index 6012cf0..31eaa7a 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -32,4 +32,4 @@ jobs:
- name: Build scrapper Docker image
- run: docker build -t scrapper-image -f Dockerfile .
+ run: docker build -t scrapper-image -f scrapper.Dockerfile .
From a22009a77e7432ce11491aa181af1727ce3c2631 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 04:09:06 +0500
Subject: [PATCH 44/61] =?UTF-8?q?=D0=97=D0=B0=D0=BF=D1=83=D1=81=D0=BA=20?=
=?UTF-8?q?=D0=BA=D0=BE=D0=BD=D1=82=D0=B5=D0=B9=D0=BD=D0=B5=D1=80=D0=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index 31eaa7a..5a215c9 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -32,4 +32,4 @@ jobs:
- name: Build scrapper Docker image
- run: docker build -t scrapper-image -f scrapper.Dockerfile .
+ run: cd FP && docker build -t scrapper-image -f scrapper.Dockerfile .
From 6c19564f4c989bcc2edc16d9f917f541c10d91be Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 04:25:54 +0500
Subject: [PATCH 45/61] =?UTF-8?q?=D0=9E=D1=82=D0=BA=D0=B0=D1=82=20=D0=BF?=
=?UTF-8?q?=D0=BE=D0=BC=D0=BD=D0=B8=D0=BA=D0=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
FP/scrapper.Dockerfile | 2 +-
FP/scrapper/pom.xml | 74 ++++++++++++++++++++----------------------
2 files changed, 37 insertions(+), 39 deletions(-)
diff --git a/FP/scrapper.Dockerfile b/FP/scrapper.Dockerfile
index 453a446..e8d2a7c 100644
--- a/FP/scrapper.Dockerfile
+++ b/FP/scrapper.Dockerfile
@@ -1,4 +1,4 @@
FROM openjdk:20
WORKDIR /app/scrapper
-COPY target/scrapper-1.0.jar scrapper.jar
+COPY scrapper/target/scrapper-1.0.jar scrapper.jar
CMD ["java", "-jar", "scrapper.jar"]
\ No newline at end of file
diff --git a/FP/scrapper/pom.xml b/FP/scrapper/pom.xml
index e214fdf..2128293 100644
--- a/FP/scrapper/pom.xml
+++ b/FP/scrapper/pom.xml
@@ -1,94 +1,96 @@
-
- 4.0.0
+
- FP
org.example
+ FP
1.0
- org.example
- scrapper
- 1.0
+ 4.0.0
- scrapper
+ scrapper
- UTF-8
- 19
- 19
+ 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-web
+ ${starter-web.version}
-
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
+ org.example
+ link-parser
+ 1.0
+ compile
-
+
+
org.springframework.boot
spring-boot-starter-webflux
+ 3.0.5
-
+
org.testcontainers
junit-jupiter
test
-
org.testcontainers
postgresql
test
-
org.liquibase
liquibase-core
test
-
+
org.springframework.boot
spring-boot-starter-jdbc
-
org.postgresql
postgresql
@@ -103,24 +105,20 @@
- org.springframework.boot
- spring-boot-starter-test
+ org.junit.jupiter
+ junit-jupiter
test
-
-
- org.springframework.boot
- spring-boot-starter-jooq
-
-
- org.springframework.boot
- spring-boot-starter-data-jpa
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.2
-
+
org.springframework.boot
spring-boot-starter-amqp
+ 3.0.6
From 5dcf5c0e8089f5bb4bdcc30dbcb5fe63ead37f02 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 04:47:15 +0500
Subject: [PATCH 46/61] Git publisher
---
.github/workflows/scrapper.yml | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index 5a215c9..6bcde87 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -10,6 +10,10 @@ on:
- 'FP/scrapper/**'
- '.github/workflows/scrapper.yml'
+env:
+ REGISTRY: ghcr.io
+ IMAGE_NAME: ${{ github.repository }}
+
jobs:
build:
runs-on: ubuntu-latest
@@ -30,6 +34,18 @@ jobs:
- name: Build with Maven
run: cd FP && mvn package -pl scrapper -am
-
- - name: Build scrapper Docker image
- run: cd FP && docker build -t scrapper-image -f scrapper.Dockerfile .
+ - name: Log in to the Container registry
+ uses: docker/login-action@v2
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Build and push
+ uses: docker/build-push-action@v3
+ with:
+ context: .
+ file: FP/scrapper.Dockerfile
+ push: ${{ github.ref_type == 'tag' }}
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
From 40c79c48d2dbf4ef9dc5fa1dcd311b35ee399958 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 04:56:04 +0500
Subject: [PATCH 47/61] Git publisher
---
.github/workflows/scrapper.yml | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index 6bcde87..e199e3b 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -45,7 +45,6 @@ jobs:
uses: docker/build-push-action@v3
with:
context: .
- file: FP/scrapper.Dockerfile
- push: ${{ github.ref_type == 'tag' }}
+ push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
From 3f82effa86e563545830e0cb0bf96ca897ee9ca1 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 04:58:25 +0500
Subject: [PATCH 48/61] Git publisher
---
.github/workflows/scrapper.yml | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index e199e3b..c897690 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -17,9 +17,6 @@ env:
jobs:
build:
runs-on: ubuntu-latest
- permissions:
- contents: read
- packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
@@ -45,6 +42,5 @@ jobs:
uses: docker/build-push-action@v3
with:
context: .
- push: true
- tags: ${{ steps.meta.outputs.tags }}
- labels: ${{ steps.meta.outputs.labels }}
+ dockerfile: FP/scrapper.Dockerfile
+ image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
From 9964605dae9b6e08344c3f5a0250f71c9ca92860 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 05:03:30 +0500
Subject: [PATCH 49/61] Git publisher
---
.github/workflows/scrapper.yml | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index c897690..aebcb19 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -39,8 +39,6 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
- uses: docker/build-push-action@v3
+ uses: docker/build-push-action@v2
with:
context: .
- dockerfile: FP/scrapper.Dockerfile
- image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
From 6bbc8fbac463098b0ec344655dd3eacc06facab6 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 05:09:20 +0500
Subject: [PATCH 50/61] Git publisher
---
.github/workflows/scrapper.yml | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index aebcb19..ec5d85b 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -17,6 +17,9 @@ env:
jobs:
build:
runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
@@ -37,8 +40,9 @@ jobs:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Build and push
- uses: docker/build-push-action@v2
- with:
- context: .
+
+ - name: Build scrapper Docker image
+ run: cd FP && docker build -t scrapper-image -f scrapper.Dockerfile .
+
+ - name: Push Docker image to GitHub Container Registry
+ run: docker push javaguava/scrapper:latest
From 110679805d6a40750b4696361db4cb701fb2b258 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 05:11:40 +0500
Subject: [PATCH 51/61] Git publisher
---
.github/workflows/scrapper.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index ec5d85b..86f0571 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -45,4 +45,4 @@ jobs:
run: cd FP && docker build -t scrapper-image -f scrapper.Dockerfile .
- name: Push Docker image to GitHub Container Registry
- run: docker push javaguava/scrapper:latest
+ run: docker push ghcr.io/javaguava/scrapper:latest
From 037b81ae7847de0c2787fa6b0659388a73094538 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 05:18:28 +0500
Subject: [PATCH 52/61] Git publisher
---
.github/workflows/scrapper.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index 86f0571..36c5c3a 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -45,4 +45,4 @@ jobs:
run: cd FP && docker build -t scrapper-image -f scrapper.Dockerfile .
- name: Push Docker image to GitHub Container Registry
- run: docker push ghcr.io/javaguava/scrapper:latest
+ run: docker push ghcr.io/${{ github.repository }}/scrapper:latest
From 5d1d6843c325c0762429b64cc842e40b3ad1f6f0 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 05:20:22 +0500
Subject: [PATCH 53/61] Git publisher
---
.github/workflows/scrapper.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index 36c5c3a..3837cb2 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -45,4 +45,4 @@ jobs:
run: cd FP && docker build -t scrapper-image -f scrapper.Dockerfile .
- name: Push Docker image to GitHub Container Registry
- run: docker push ghcr.io/${{ github.repository }}/scrapper:latest
+ run: docker push ghcr.io/ray-not/javaguava/scrapper:latest
From 9cecb09cfbc30e639cb73796f56ae481f728b1e5 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 05:22:49 +0500
Subject: [PATCH 54/61] Git publisher
---
.github/workflows/scrapper.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index 3837cb2..6517e62 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -42,7 +42,7 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build scrapper Docker image
- run: cd FP && docker build -t scrapper-image -f scrapper.Dockerfile .
+ run: cd FP && docker build -t scrapper-image -f scrapper.Dockerfile ray-not/javaguava/scrapper:latest
- name: Push Docker image to GitHub Container Registry
run: docker push ghcr.io/ray-not/javaguava/scrapper:latest
From 56a5971f12f8006cff938de32b831f9e74048daa Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 05:25:53 +0500
Subject: [PATCH 55/61] Git publisher
---
.github/workflows/scrapper.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index 6517e62..f40f505 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -42,7 +42,7 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build scrapper Docker image
- run: cd FP && docker build -t scrapper-image -f scrapper.Dockerfile ray-not/javaguava/scrapper:latest
+ run: cd FP && docker build -t scrapper-image -f scrapper.Dockerfile -t ray-not/javaguava/scrapper:latest
- name: Push Docker image to GitHub Container Registry
run: docker push ghcr.io/ray-not/javaguava/scrapper:latest
From 6714c6109cc2ecb1de934d7b1763319db5161b06 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 05:28:23 +0500
Subject: [PATCH 56/61] Git publisher
---
.github/workflows/scrapper.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index f40f505..5c8b024 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -42,7 +42,7 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build scrapper Docker image
- run: cd FP && docker build -t scrapper-image -f scrapper.Dockerfile -t ray-not/javaguava/scrapper:latest
+ run: cd FP && docker build -t scrapper-image -f scrapper.Dockerfile -t ray-not/javaguava/scrapper:latest .
- name: Push Docker image to GitHub Container Registry
run: docker push ghcr.io/ray-not/javaguava/scrapper:latest
From efd38ae7f869d856de9e920fb6390dd1e1c343f6 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 05:35:09 +0500
Subject: [PATCH 57/61] Git publisher
---
.github/workflows/scrapper.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index 5c8b024..fef2745 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -42,7 +42,7 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build scrapper Docker image
- run: cd FP && docker build -t scrapper-image -f scrapper.Dockerfile -t ray-not/javaguava/scrapper:latest .
+ run: cd FP && docker build -f scrapper.Dockerfile -t ghcr.io/ray-not/javaguava/scrapper:latest .
- name: Push Docker image to GitHub Container Registry
run: docker push ghcr.io/ray-not/javaguava/scrapper:latest
From 6a2eca1dab698c21aeaf5fd9026a124649f109f9 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 06:37:38 +0500
Subject: [PATCH 58/61] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?=
=?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=202=20=D0=BA=D0=BE=D0=BD=D1=84=D0=B8?=
=?UTF-8?q?=D0=B3=D0=BE=D0=B2=20=D0=B8=20checkstyle?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/scrapper.yml | 16 ++++++++++++++++
FP/.editorconfig | 17 +++++++++++++++++
FP/checkstyle.xml | 11 +++++++++++
3 files changed, 44 insertions(+)
create mode 100644 FP/.editorconfig
create mode 100644 FP/checkstyle.xml
diff --git a/.github/workflows/scrapper.yml b/.github/workflows/scrapper.yml
index fef2745..d2f9670 100644
--- a/.github/workflows/scrapper.yml
+++ b/.github/workflows/scrapper.yml
@@ -46,3 +46,19 @@ jobs:
- name: Push Docker image to GitHub Container Registry
run: docker push ghcr.io/ray-not/javaguava/scrapper:latest
+ checkstyle:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - name: Set up JDK 20
+ uses: actions/setup-java@v3
+ with:
+ java-version: '20'
+ distribution: 'temurin'
+
+ - name: Format code
+ run: cd FP && mvn -pl scrapper -am checkstyle:check
diff --git a/FP/.editorconfig b/FP/.editorconfig
new file mode 100644
index 0000000..7f7a11a
--- /dev/null
+++ b/FP/.editorconfig
@@ -0,0 +1,17 @@
+root = true
+
+[*]
+charset = utf-8
+tab_width = 4
+indent_size = 4
+indent_style = space
+max_line_length = 120
+insert_final_newline = true
+trim_trailing_whitespace = true
+ij_continuation_indent_size = 4
+
+[*.java]
+ij_java_imports_layout = *, $*
+ij_java_packages_to_use_import_on_demand = ""
+ij_java_class_count_to_use_import_on_demand = 999
+ij_java_names_count_to_use_import_on_demand = 999
\ No newline at end of file
diff --git a/FP/checkstyle.xml b/FP/checkstyle.xml
new file mode 100644
index 0000000..d22c8f5
--- /dev/null
+++ b/FP/checkstyle.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
From cacba8bae516670568fee942e16716f8bf7bbbf6 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 06:40:38 +0500
Subject: [PATCH 59/61] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?=
=?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=202=20=D0=BA=D0=BE=D0=BD=D1=84=D0=B8?=
=?UTF-8?q?=D0=B3=D0=BE=D0=B2=20=D0=B8=20checkstyle?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
FP/.editorconfig | 11 +----------
FP/checkstyle.xml | 2 --
2 files changed, 1 insertion(+), 12 deletions(-)
diff --git a/FP/.editorconfig b/FP/.editorconfig
index 7f7a11a..e9187c4 100644
--- a/FP/.editorconfig
+++ b/FP/.editorconfig
@@ -2,16 +2,7 @@ root = true
[*]
charset = utf-8
-tab_width = 4
-indent_size = 4
-indent_style = space
-max_line_length = 120
-insert_final_newline = true
-trim_trailing_whitespace = true
ij_continuation_indent_size = 4
[*.java]
-ij_java_imports_layout = *, $*
-ij_java_packages_to_use_import_on_demand = ""
-ij_java_class_count_to_use_import_on_demand = 999
-ij_java_names_count_to_use_import_on_demand = 999
\ No newline at end of file
+ij_java_packages_to_use_import_on_demand = ""
\ No newline at end of file
diff --git a/FP/checkstyle.xml b/FP/checkstyle.xml
index d22c8f5..f6fa8d9 100644
--- a/FP/checkstyle.xml
+++ b/FP/checkstyle.xml
@@ -4,8 +4,6 @@
-
-
\ No newline at end of file
From d030c2b11dd2ce1ac70b9a8430099afdb38c4067 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 06:48:30 +0500
Subject: [PATCH 60/61] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?=
=?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=B2=20pom=20link=20=D0=BF=D0=B0=D1=80?=
=?UTF-8?q?=D1=81=D0=B5=D1=80=D0=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
FP/.editorconfig | 4 +---
FP/checkstyle.xml | 5 -----
FP/link-parser/pom.xml | 5 -----
3 files changed, 1 insertion(+), 13 deletions(-)
diff --git a/FP/.editorconfig b/FP/.editorconfig
index e9187c4..b43f001 100644
--- a/FP/.editorconfig
+++ b/FP/.editorconfig
@@ -2,7 +2,5 @@ root = true
[*]
charset = utf-8
-ij_continuation_indent_size = 4
-[*.java]
-ij_java_packages_to_use_import_on_demand = ""
\ No newline at end of file
+[*.java]
\ No newline at end of file
diff --git a/FP/checkstyle.xml b/FP/checkstyle.xml
index f6fa8d9..76dd56a 100644
--- a/FP/checkstyle.xml
+++ b/FP/checkstyle.xml
@@ -2,8 +2,3 @@
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
-
-
-
-
-
\ No newline at end of file
diff --git a/FP/link-parser/pom.xml b/FP/link-parser/pom.xml
index 8de37c0..b9572e6 100644
--- a/FP/link-parser/pom.xml
+++ b/FP/link-parser/pom.xml
@@ -62,11 +62,6 @@
maven-failsafe-plugin
2.22.2
-
- org.apache.maven.plugins
- maven-surefire-plugin
- 2.22.2
-
From ec0000756cd0e6f4498742ec495490cb4e5dd382 Mon Sep 17 00:00:00 2001
From: Ray-Not <2sinsincuba@gmail.com>
Date: Sat, 20 May 2023 06:54:12 +0500
Subject: [PATCH 61/61] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?=
=?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=BA=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=D1=83?=
=?UTF-8?q?=D1=80=D0=B0=D1=86=D0=B8=D1=8F=20editor=20=D0=B8=20checkstyle?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
FP/.editorconfig | 7 ++++++-
FP/checkstyle.xml | 8 ++++++++
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/FP/.editorconfig b/FP/.editorconfig
index b43f001..10b0c57 100644
--- a/FP/.editorconfig
+++ b/FP/.editorconfig
@@ -2,5 +2,10 @@ root = true
[*]
charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
-[*.java]
\ No newline at end of file
+[*.java]
+indent_style = space
+indent_size = 4
diff --git a/FP/checkstyle.xml b/FP/checkstyle.xml
index 76dd56a..fad9bdd 100644
--- a/FP/checkstyle.xml
+++ b/FP/checkstyle.xml
@@ -2,3 +2,11 @@
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
+
+
+
+
+
+
+
+