From d665dd242b8d410c802c1ee80a310020f8cf4e0a Mon Sep 17 00:00:00 2001 From: Ray <113240139+Ray-Not@users.noreply.github.com> Date: Tue, 2 May 2023 18:26:28 +0500 Subject: [PATCH 1/9] Create README.md --- README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..dbfb550 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# JavaGuava From 56bca09ecd5837cf9072fb6f4388ba84cf603899 Mon Sep 17 00:00:00 2001 From: Ray-Not <2sinsincuba@gmail.com> Date: Mon, 15 May 2023 14:16:30 +0500 Subject: [PATCH 2/9] Add hw7 --- FP/.project | 18 ++ FP/bot/.classpath | 34 +++ FP/bot/.dbeaver/.credentials-config.json.bak | Bin 0 -> 112 bytes FP/bot/.dbeaver/.data-sources.json.bak | 4 + FP/bot/.dbeaver/.project-metadata.json.bak | 1 + FP/bot/.dbeaver/data-sources.json | 6 + FP/bot/.dbeaver/project-metadata.json | 1 + FP/bot/.dbeaver/project-settings.json | 1 + FP/bot/.gitignore | 1 + FP/bot/.project | 24 ++ .../org.eclipse.core.resources.prefs | 6 + FP/bot/.settings/org.eclipse.jdt.core.prefs | 9 + FP/bot/.settings/org.eclipse.m2e.core.prefs | 4 + FP/bot/pom.xml | 103 +++++++ .../tinkoff/edu/java/bot/BotApplication.java | 16 ++ .../java/bot/advice/AppExceptionHandler.java | 23 ++ .../edu/java/bot/client/ScrapperClient.java | 97 +++++++ .../bot/client/ScrapperClientException.java | 11 + .../edu/java/bot/commands/Command.java | 20 ++ .../edu/java/bot/commands/CommandsEnum.java | 33 +++ .../edu/java/bot/commands/HelpCommand.java | 23 ++ .../edu/java/bot/commands/ListCommand.java | 48 ++++ .../edu/java/bot/commands/StartCommand.java | 55 ++++ .../edu/java/bot/commands/TrackCommand.java | 47 ++++ .../edu/java/bot/commands/UntrackCommand.java | 49 ++++ .../bot/configuration/ApplicationConfig.java | 12 + .../bot/configuration/BotConfiguration.java | 66 +++++ .../configuration/ClientConfiguration.java | 27 ++ .../LinkParserConfiguration.java | 14 + .../configuration/RabbitMQConfiguration.java | 80 ++++++ .../edu/java/bot/dto/AddLinkRequest.java | 6 + .../edu/java/bot/dto/ApiErrorResponse.java | 7 + .../tinkoff/edu/java/bot/dto/BotCommand.java | 8 + .../ru/tinkoff/edu/java/bot/dto/Link.java | 10 + .../edu/java/bot/dto/LinkResponse.java | 11 + .../tinkoff/edu/java/bot/dto/LinkUpdate.java | 5 + .../edu/java/bot/dto/ListLinkResponse.java | 6 + .../edu/java/bot/dto/RemoveLinkRequest.java | 5 + .../edu/java/bot/dto/SetCommandRequest.java | 7 + .../tinkoff/edu/java/bot/dto/UserAddDto.java | 8 + .../bot/exceptions/ChatNotFoundException.java | 10 + .../LinkIsNotRegisteredToChatException.java | 10 + .../edu/java/bot/rest/BotRestController.java | 30 +++ .../bot/service/ScrapperQueueListener.java | 32 +++ .../edu/java/bot/service/UpdateService.java | 8 + .../java/bot/service/UpdateServiceImpl.java | 26 ++ .../ru/tinkoff/edu/java/bot/telegram/Bot.java | 53 ++++ .../bot/telegram/UserMessageProcessor.java | 67 +++++ .../edu/java/bot/telegram/UserState.java | 5 + .../src/main/resources/application.properties | 13 + FP/bot/src/test/java/bot/BotTest.java | 123 +++++++++ FP/docker-compose.yml | 60 +++++ FP/link-parser/.classpath | 41 +++ FP/link-parser/.gitignore | 1 + FP/link-parser/.project | 23 ++ .../org.eclipse.core.resources.prefs | 6 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../.settings/org.eclipse.m2e.core.prefs | 4 + FP/link-parser/pom.xml | 30 +++ .../java/link_parser/link/GitHub_Link.java | 5 + .../java/link_parser/link/Parser_Link.java | 5 + .../link_parser/link/StackOverflow_Link.java | 5 + .../edu/java/link_parser/parser/Abstract.java | 27 ++ .../edu/java/link_parser/parser/Github.java | 31 +++ .../java/link_parser/parser/Link_Parser.java | 16 ++ .../link_parser/parser/StackOverflow.java | 34 +++ .../src/test/java/LinkParserTest.java | 99 +++++++ FP/migrations/01-schema-1.sql | 11 + FP/migrations/02-schema-2.sql | 15 ++ FP/migrations/03-schema-3.sql | 10 + FP/migrations/create.sql | 18 ++ FP/migrations/delete.sql | 3 + FP/migrations/insert.sql | 37 +++ FP/migrations/master.xml | 13 + FP/pom.xml | 123 +++++++++ FP/scrapper-jooq/.classpath | 28 ++ FP/scrapper-jooq/.gitignore | 1 + FP/scrapper-jooq/.project | 23 ++ .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../.settings/org.eclipse.m2e.core.prefs | 4 + FP/scrapper-jooq/pom.xml | 40 +++ .../src/main/java/JooqCodegen.java | 49 ++++ FP/scrapper/.classpath | 41 +++ FP/scrapper/.gitignore | 1 + FP/scrapper/.project | 23 ++ .../org.eclipse.core.resources.prefs | 6 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../.settings/org.eclipse.m2e.core.prefs | 4 + FP/scrapper/pom.xml | 120 +++++++++ .../java/scrapper/ScrapperApplication.java | 22 ++ .../scrapper/advice/AppExceptionHandler.java | 33 +++ .../edu/java/scrapper/client/BotClient.java | 38 +++ .../java/scrapper/client/GitHubClient.java | 47 ++++ .../scrapper/client/StackOverflowClient.java | 44 +++ .../configuration/ApplicationConfig.java | 26 ++ .../configuration/ClientConfiguration.java | 44 +++ .../configuration/HTTPConfiguration.java | 28 ++ .../LinkParserConfiguration.java | 14 + .../configuration/RabbitMQConfiguration.java | 50 ++++ .../acess/JdbcAccessConfiguration.java | 99 +++++++ .../acess/JooqAccessConfiguration.java | 84 ++++++ .../acess/JpaAccessConfiguration.java | 61 +++++ .../edu/java/scrapper/dto/AddLinkRequest.java | 5 + .../java/scrapper/dto/ApiErrorResponse.java | 6 + .../edu/java/scrapper/dto/GitHubResponse.java | 25 ++ .../edu/java/scrapper/dto/LinkResponse.java | 5 + .../edu/java/scrapper/dto/LinkUpdate.java | 5 + .../java/scrapper/dto/ListLinkResponse.java | 8 + .../java/scrapper/dto/RemoveLinkRequest.java | 5 + .../java/scrapper/dto/StackOverflowItem.java | 8 + .../scrapper/dto/StackOverflowResponse.java | 8 + .../edu/java/scrapper/dto/UserAddDto.java | 8 + .../BadResponseFromApiException.java | 12 + .../exception/BotClientException.java | 11 + .../exception/ChatAlreadyExistException.java | 11 + .../exception/ChatNotFoundException.java | 12 + .../exception/GitHubRequestException.java | 11 + .../LinkIsAlreadyAddedException.java | 12 + .../exception/LinkNotFoundException.java | 12 + .../StackOverflowRequestException.java | 12 + .../java/scrapper/mapper/LinkRowMapper.java | 27 ++ .../mapper/SubscriptionRowMapper.java | 20 ++ .../java/scrapper/mapper/UserRowMapper.java | 24 ++ .../java/scrapper/model/commonDto/Link.java | 31 +++ .../java/scrapper/model/commonDto/User.java | 32 +++ .../scrapper/model/jdbcAndJooq/Relation.java | 11 + .../java/scrapper/model/jpa/LinkEntity.java | 40 +++ .../java/scrapper/model/jpa/UserEntity.java | 30 +++ .../jdbc/LinkJdbcTemplateRepository.java | 86 ++++++ .../SubscriptionJdbcTemplateRepository.java | 75 ++++++ .../jdbc/UserJdbcTemplateRepository.java | 59 ++++ .../jdbcAndJooqContract/LinkRepository.java | 21 ++ .../SubscriptionRepository.java | 19 ++ .../jdbcAndJooqContract/UserRepository.java | 13 + .../repository/jooq/LinkJooqRepository.java | 98 +++++++ .../jooq/SubscriptionJooqRepository.java | 80 ++++++ .../repository/jooq/UserJooqRepository.java | 59 ++++ .../repository/jpa/JpaLinkRepository.java | 20 ++ .../repository/jpa/JpaUserRepository.java | 22 ++ .../scrapper/rest/ChatRestController.java | 30 +++ .../scrapper/rest/LinkRestController.java | 44 +++ .../schedule/LinkUpdateScheduler.java | 26 ++ .../edu/java/scrapper/schedule/Scheduler.java | 6 + .../service/ScrapperQueueProducer.java | 26 ++ .../service/UpdateNotificationService.java | 8 + .../service/contract/LinkUpdateService.java | 12 + .../service/contract/SubscriptionService.java | 14 + .../service/contract/TgChatService.java | 11 + .../impl/LinkUpdateServiceImpl.java | 156 +++++++++++ .../impl/SubscriptionServiceImpl.java | 99 +++++++ .../jdbcAndJooq/impl/TgChatServiceImpl.java | 42 +++ .../jpa/impl/JpaLinkUpdateServiceImpl.java | 174 ++++++++++++ .../jpa/impl/JpaSubscriptionServiceImpl.java | 100 +++++++ .../jpa/impl/JpaTgChatServiceImpl.java | 43 +++ .../src/main/resources/application.properties | 23 ++ .../src/main/resources/logback-test.xml | 17 ++ .../src/test/java/scrapper/DatabaseTest.java | 38 +++ .../java/scrapper/IntegrationEnvironment.java | 54 ++++ .../scrapper/environment/DatabaseTest.java | 38 +++ .../environment/IntegrationEnvironment.java | 81 ++++++ .../environment/TestConfiguration.java | 8 + .../test/java/scrapper/jdbc/JdbcLinkTest.java | 151 +++++++++++ .../scrapper/jdbc/JdbcSubscriptionTest.java | 251 ++++++++++++++++++ .../test/java/scrapper/jdbc/JdbcUserTest.java | 135 ++++++++++ 165 files changed, 5391 insertions(+) create mode 100644 FP/.project create mode 100644 FP/bot/.classpath create mode 100644 FP/bot/.dbeaver/.credentials-config.json.bak create mode 100644 FP/bot/.dbeaver/.data-sources.json.bak create mode 100644 FP/bot/.dbeaver/.project-metadata.json.bak create mode 100644 FP/bot/.dbeaver/data-sources.json create mode 100644 FP/bot/.dbeaver/project-metadata.json create mode 100644 FP/bot/.dbeaver/project-settings.json create mode 100644 FP/bot/.gitignore create mode 100644 FP/bot/.project create mode 100644 FP/bot/.settings/org.eclipse.core.resources.prefs create mode 100644 FP/bot/.settings/org.eclipse.jdt.core.prefs create mode 100644 FP/bot/.settings/org.eclipse.m2e.core.prefs create mode 100644 FP/bot/pom.xml create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java create mode 100644 FP/bot/src/main/resources/application.properties create mode 100644 FP/bot/src/test/java/bot/BotTest.java create mode 100644 FP/docker-compose.yml create mode 100644 FP/link-parser/.classpath create mode 100644 FP/link-parser/.gitignore create mode 100644 FP/link-parser/.project create mode 100644 FP/link-parser/.settings/org.eclipse.core.resources.prefs create mode 100644 FP/link-parser/.settings/org.eclipse.jdt.core.prefs create mode 100644 FP/link-parser/.settings/org.eclipse.m2e.core.prefs create mode 100644 FP/link-parser/pom.xml create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/GitHub_Link.java create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/Parser_Link.java create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/StackOverflow_Link.java create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Link_Parser.java create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java create mode 100644 FP/link-parser/src/test/java/LinkParserTest.java create mode 100644 FP/migrations/01-schema-1.sql create mode 100644 FP/migrations/02-schema-2.sql create mode 100644 FP/migrations/03-schema-3.sql create mode 100644 FP/migrations/create.sql create mode 100644 FP/migrations/delete.sql create mode 100644 FP/migrations/insert.sql create mode 100644 FP/migrations/master.xml create mode 100644 FP/pom.xml create mode 100644 FP/scrapper-jooq/.classpath create mode 100644 FP/scrapper-jooq/.gitignore create mode 100644 FP/scrapper-jooq/.project create mode 100644 FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs create mode 100644 FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs create mode 100644 FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs create mode 100644 FP/scrapper-jooq/pom.xml create mode 100644 FP/scrapper-jooq/src/main/java/JooqCodegen.java create mode 100644 FP/scrapper/.classpath create mode 100644 FP/scrapper/.gitignore create mode 100644 FP/scrapper/.project create mode 100644 FP/scrapper/.settings/org.eclipse.core.resources.prefs create mode 100644 FP/scrapper/.settings/org.eclipse.jdt.core.prefs create mode 100644 FP/scrapper/.settings/org.eclipse.m2e.core.prefs create mode 100644 FP/scrapper/pom.xml create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java create mode 100644 FP/scrapper/src/main/resources/application.properties create mode 100644 FP/scrapper/src/main/resources/logback-test.xml create mode 100644 FP/scrapper/src/test/java/scrapper/DatabaseTest.java create mode 100644 FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java create mode 100644 FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java create mode 100644 FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java create mode 100644 FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java create mode 100644 FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java create mode 100644 FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java create mode 100644 FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java diff --git a/FP/.project b/FP/.project new file mode 100644 index 0000000..89d138f --- /dev/null +++ b/FP/.project @@ -0,0 +1,18 @@ + + + project + + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + org.jkiss.dbeaver.DBeaverNature + + diff --git a/FP/bot/.classpath b/FP/bot/.classpath new file mode 100644 index 0000000..0b9fa8d --- /dev/null +++ b/FP/bot/.classpath @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FP/bot/.dbeaver/.credentials-config.json.bak b/FP/bot/.dbeaver/.credentials-config.json.bak new file mode 100644 index 0000000000000000000000000000000000000000..8320c631e208c3ad7467cf2d9db83d85e90f14f8 GIT binary patch literal 112 zcmV-$0FVC>%bw`qlvu4i=Wrho)ja=8tm(6RtT%VUiv(RbXd+9@8O^=>KI816Agz S3>36s#U(-2xgbD9^um4; + + bot + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.jkiss.dbeaver.DBeaverNature + + diff --git a/FP/bot/.settings/org.eclipse.core.resources.prefs b/FP/bot/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..29abf99 --- /dev/null +++ b/FP/bot/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding//src/test/resources=UTF-8 +encoding/=UTF-8 diff --git a/FP/bot/.settings/org.eclipse.jdt.core.prefs b/FP/bot/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..5e4ec05 --- /dev/null +++ b/FP/bot/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/FP/bot/.settings/org.eclipse.m2e.core.prefs b/FP/bot/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/FP/bot/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/FP/bot/pom.xml b/FP/bot/pom.xml new file mode 100644 index 0000000..11dc02c --- /dev/null +++ b/FP/bot/pom.xml @@ -0,0 +1,103 @@ + + 4.0.0 + + project + project + 0.0.1-SNAPSHOT + + bot + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-webflux + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.springframework + spring-context-indexer + true + + + org.projectlombok + lombok + true + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.0.2 + + + com.github.pengrad + java-telegram-bot-api + 6.6.0 + + + ru.tinkoff.edu + link-parser + 1.0-SNAPSHOT + + + org.springframework + spring-context + 6.0.3 + + + org.springframework + spring-test + 6.0.6 + test + + + org.junit.jupiter + junit-jupiter-params + + + org.mockito + mockito-core + + + org.springframework.boot + spring-boot-starter-amqp + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-failsafe-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + + + \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java new file mode 100644 index 0000000..50cd2b8 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java @@ -0,0 +1,16 @@ +package ru.tinkoff.edu.java.bot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import ru.tinkoff.edu.java.bot.configuration.ApplicationConfig; + +@SpringBootApplication +@EnableConfigurationProperties(ApplicationConfig.class) +public class BotApplication { + public static void main(String[] args) { + var ctx = SpringApplication.run(BotApplication.class, args); + ApplicationConfig config = ctx.getBean(ApplicationConfig.class); + + } +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java new file mode 100644 index 0000000..12c0975 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java @@ -0,0 +1,23 @@ +package ru.tinkoff.edu.java.bot.advice; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import ru.tinkoff.edu.java.bot.dto.ApiErrorResponse; +import ru.tinkoff.edu.java.bot.exceptions.ChatNotFoundException; +import ru.tinkoff.edu.java.bot.exceptions.LinkIsNotRegisteredToChatException; + +import java.util.Arrays; + +@RestControllerAdvice +public class AppExceptionHandler { + + @ExceptionHandler({LinkIsNotRegisteredToChatException.class, ChatNotFoundException.class}) + @ResponseStatus(value = HttpStatus.BAD_REQUEST) + public ApiErrorResponse handleNotFoundExceptions(RuntimeException exception) { + return new ApiErrorResponse( + "Error", HttpStatus.BAD_REQUEST.toString(), exception.getClass().getName(), exception.getMessage(), Arrays.stream(exception.getStackTrace()).map(StackTraceElement::toString).toList().toArray(String[]::new)); + } + +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java new file mode 100644 index 0000000..f8ef3a4 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java @@ -0,0 +1,97 @@ +package ru.tinkoff.edu.java.bot.client; + +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; +import ru.tinkoff.edu.java.bot.dto.*; + + +public class ScrapperClient { + + private final WebClient webClient; + + + //По умолчанию - webClient инжектится из ClientConfiguration c baseUrl по умолчанию + public ScrapperClient(WebClient webClient) { + this.webClient = webClient; + } + + //Здесь webClient не инжектится, чтобы была возможность указать baseUrl. + public ScrapperClient(String baseUrl) { + this.webClient = WebClient.create(baseUrl); + } + + + public ListLinkResponse getLinks(Long tgChatId) { + ListLinkResponse response = webClient.get().uri("/links").header("Tg-Chat-Id", String.valueOf(tgChatId)).exchangeToMono(r -> { + if (r.statusCode().equals(HttpStatus.NOT_FOUND)) { + throw new ScrapperClientException("Чат с таким ID не зарегистрирован"); + } else if (r.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) { + throw new ScrapperClientException("Что-то пошло не так. Проблема на нашей стороне, повторите попытку позже"); + } + return r.bodyToMono(ListLinkResponse.class); + }).block(); + + return response; + } + + public LinkResponse addLink(Long tgChatId, AddLinkRequest request) { + LinkResponse response = webClient.post().uri("/links").header("Tg-Chat-Id", String.valueOf(tgChatId)) + .bodyValue(request).exchangeToMono(r -> { + if (r.statusCode().equals(HttpStatus.BAD_REQUEST)) { + throw new ScrapperClientException("Ссылка с таким URL уже добавлена"); + } else if (r.statusCode().equals(HttpStatus.NOT_FOUND)) { + throw new ScrapperClientException("Чат с таким ID не зарегистрирован"); + } else if (r.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) { + throw new ScrapperClientException("Что-то пошло не так. Проблема на нашей стороне, повторите попытку позже"); + } + return r.bodyToMono(LinkResponse.class); + }).block(); + + return response; + } + + public LinkResponse deleteLink(Long tgChatId, RemoveLinkRequest request) { + LinkResponse response = webClient.method(HttpMethod.DELETE).uri("/links").header("Tg-Chat-Id", String.valueOf(tgChatId)) + .bodyValue(request).exchangeToMono(r -> { + if (r.statusCode().equals(HttpStatus.BAD_REQUEST)) { + throw new ScrapperClientException("Некорректно указана ссылка"); + } else if (r.statusCode().equals(HttpStatus.NOT_FOUND)) { + throw new ScrapperClientException("Ссылка с таким URL не найдена или чат с таким ID не зарегистрирован"); + } else if (r.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) { + throw new ScrapperClientException("Что-то пошло не так. Проблема на нашей стороне, повторите попытку позже"); + } + return r.bodyToMono(LinkResponse.class); + }).block(); + + return response; + } + + + public void registerChat(Long tgChatId, UserAddDto userAddDto) { + webClient.post().uri("/tg-chat/{id}", tgChatId).bodyValue(userAddDto).exchangeToMono(response -> { + if (response.statusCode().equals(HttpStatus.BAD_REQUEST)) { + throw new ScrapperClientException("Некорректно указан ID или такой чат уже зарегистрирован"); + } else if (response.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) { + throw new ScrapperClientException("Что-то пошло не так. Проблема на нашей стороне, повторите попытку позже"); + } + return Mono.empty(); + }).block(); + } + + public void deleteChat(Long tgChatId) { + webClient.delete().uri("/tg-chat/{id}", tgChatId).exchangeToMono(response -> { + if (response.statusCode().equals(HttpStatus.BAD_REQUEST)) { + throw new ScrapperClientException("Некорректно указан ID"); + } else if (response.statusCode().equals(HttpStatus.NOT_FOUND)) { + throw new ScrapperClientException("Чат с таким ID не найден"); + } else if (response.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) { + throw new ScrapperClientException("Что-то пошло не так. Проблема на нашей стороне, повторите попытку позже"); + } + return Mono.empty(); + }).block(); + } + + +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java new file mode 100644 index 0000000..9ef91d4 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java @@ -0,0 +1,11 @@ +package ru.tinkoff.edu.java.bot.client; + +public class ScrapperClientException extends RuntimeException{ + + public ScrapperClientException() { + } + + public ScrapperClientException(String message) { + super(message); + } +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java new file mode 100644 index 0000000..a179c88 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java @@ -0,0 +1,20 @@ +package ru.tinkoff.edu.java.bot.commands; + +import com.pengrad.telegrambot.model.Update; +import ru.tinkoff.edu.java.bot.dto.BotCommand; + +public interface Command { + String command(); + + String description(); + + String handle(Update update); + + default boolean supports(Update update) { + return update.message().text().equals(command()); + } + + default BotCommand toApiCommand() { + return new BotCommand(command(), description()); + } +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java new file mode 100644 index 0000000..1d3852c --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java @@ -0,0 +1,33 @@ +package ru.tinkoff.edu.java.bot.commands; + +import java.util.HashMap; +import java.util.Map; + +public enum CommandsEnum { + + START ("/start"), + HELP ("/help"), + LIST ("/list"), + TRACK ("/track"), + UNTRACK ("/untrack"); + + private static final Map BY_LABEL = new HashMap<>(); + + static { + for (CommandsEnum c : values()) { + BY_LABEL.put(c.label, c); + } + } + + private final String label; + + CommandsEnum(String command) { + this.label = command; + } + + public static CommandsEnum valueOfLabel(String label) { + return BY_LABEL.get(label); + } + + +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java new file mode 100644 index 0000000..3849dc7 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java @@ -0,0 +1,23 @@ +package ru.tinkoff.edu.java.bot.commands; + +import com.pengrad.telegrambot.model.Update; +import com.pengrad.telegrambot.request.SendMessage; +import org.springframework.stereotype.Component; + +@Component +public class HelpCommand implements Command{ + @Override + public String command() { + return "/help"; + } + + @Override + public String description() { + return "ввывести окно с командами"; + } + + @Override + public String handle(Update update) { + return "Help is executing..."; + } +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java new file mode 100644 index 0000000..6a3176e --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java @@ -0,0 +1,48 @@ +package ru.tinkoff.edu.java.bot.commands; + +import com.pengrad.telegrambot.model.Update; +import org.springframework.stereotype.Component; +import ru.tinkoff.edu.java.bot.client.ScrapperClient; +import ru.tinkoff.edu.java.bot.client.ScrapperClientException; +import ru.tinkoff.edu.java.bot.dto.Link; +import ru.tinkoff.edu.java.bot.dto.ListLinkResponse; + +@Component +public class ListCommand implements Command { + + private final ScrapperClient scrapperClient; + + public ListCommand(ScrapperClient scrapperClient) { + this.scrapperClient = scrapperClient; + } + + @Override + public String command() { + return "/list"; + } + + @Override + public String description() { + return "показать список отслеживаемых ссылок"; + } + + @Override + public String handle(Update update) { + long chatId = update.message().chat().id(); + try { + ListLinkResponse response = scrapperClient.getLinks(chatId); + StringBuilder msg = new StringBuilder(); + if (response.size() == 0) + msg.append("Список отслеживаемых ссылок пуст!"); + else { + msg.append("Ссылок отслеживается - ").append(response.size()).append("\n\n"); + for (Link link : response.links()) { + msg.append(link.url()).append("\n\n"); + } + } + return msg.toString(); + } catch (ScrapperClientException e){ + return e.getMessage(); + } + } +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java new file mode 100644 index 0000000..9c9f497 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java @@ -0,0 +1,55 @@ +package ru.tinkoff.edu.java.bot.commands; + +import com.pengrad.telegrambot.model.Update; +import com.pengrad.telegrambot.model.request.InlineKeyboardButton; +import com.pengrad.telegrambot.model.request.InlineKeyboardMarkup; +import com.pengrad.telegrambot.request.SendMessage; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; +import ru.tinkoff.edu.java.bot.client.ScrapperClient; +import ru.tinkoff.edu.java.bot.client.ScrapperClientException; +import ru.tinkoff.edu.java.bot.dto.Link; +import ru.tinkoff.edu.java.bot.dto.ListLinkResponse; +import ru.tinkoff.edu.java.bot.dto.UserAddDto; + +@Component +public class StartCommand implements Command { + + private final ScrapperClient scrapperClient; + + public StartCommand(ScrapperClient scrapperClient) { + this.scrapperClient = scrapperClient; + } + + + @Value("${tg.bot.token}") + private String token; + + + @Override + public String command() { + return "/start"; + } + + @Override + public String description() { + return "зарегистрировать пользователя"; + } + + @Override + public String handle(Update update) { + long chatId = update.message().chat().id(); + try { + UserAddDto userAddDto = new UserAddDto(update.message().chat().username(), update.message().chat().firstName(), update.message().chat().lastName()); + scrapperClient.registerChat(chatId, userAddDto); + return "Привет! Рад познакомиться, " + update.message().chat().firstName(); + } catch (ScrapperClientException e) { + + return e.getMessage(); + } + + + } +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java new file mode 100644 index 0000000..a3eb9b4 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java @@ -0,0 +1,47 @@ +package ru.tinkoff.edu.java.bot.commands; + +import com.pengrad.telegrambot.model.Update; +import com.pengrad.telegrambot.request.SendMessage; +import org.springframework.stereotype.Component; +import ru.tinkoff.edu.java.link_parser.parser.Link_Parser; +import ru.tinkoff.edu.java.bot.client.ScrapperClient; +import ru.tinkoff.edu.java.bot.client.ScrapperClientException; +import ru.tinkoff.edu.java.bot.dto.AddLinkRequest; + +@Component +public class TrackCommand implements Command { + + private final LinkParser parser; + + public TrackCommand(ScrapperClient scrapperClient, LinkParser parser) { + this.scrapperClient = scrapperClient; + this.parser = parser; + } + + private final ScrapperClient scrapperClient; + + @Override + public String command() { + return "/track"; + } + + @Override + public String description() { + return "начать отслеживание ссылки"; + } + + @Override + public String handle(Update update) { + long chatId = update.message().chat().id(); + String msg; + try { + if (parser.parseUrl(update.message().text()) != null){ + scrapperClient.addLink(chatId, new AddLinkRequest(update.message().text())); + msg = "Ссылка успешно добавлена"; + } else msg = "Некорректная ссылка"; + return msg; + } catch (ScrapperClientException e) { + return e.getMessage(); + } + } +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java new file mode 100644 index 0000000..df1c58a --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java @@ -0,0 +1,49 @@ +package ru.tinkoff.edu.java.bot.commands; + +import com.pengrad.telegrambot.model.Update; +import com.pengrad.telegrambot.request.SendMessage; +import org.springframework.stereotype.Component; +import ru.tinkoff.edu.java.link_parser.parser.Link_Parser; +import ru.tinkoff.edu.java.bot.client.ScrapperClient; +import ru.tinkoff.edu.java.bot.client.ScrapperClientException; +import ru.tinkoff.edu.java.bot.dto.AddLinkRequest; +import ru.tinkoff.edu.java.bot.dto.RemoveLinkRequest; + +@Component +public class UntrackCommand implements Command{ + + private final ScrapperClient scrapperClient; + + private final Link_Parser parser; + + + public UntrackCommand(ScrapperClient scrapperClient, Link_Parser parser) { + this.scrapperClient = scrapperClient; + this.parser = parser; + } + + @Override + public String command() { + return "/untrack"; + } + + @Override + public String description() { + return "прекратить отслеживание ссылки"; + } + + @Override + public String handle(Update update) { + long chatId = update.message().chat().id(); + String msg; + try { + if (parser.parseUrl(update.message().text()) != null){ + scrapperClient.deleteLink(chatId, new RemoveLinkRequest(update.message().text())); + msg = "Ссылка успешно удалена"; + } else msg = "Некорректная ссылка"; + return msg; + } catch (ScrapperClientException e) { + return e.getMessage(); + } + } +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java new file mode 100644 index 0000000..02ab1d4 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java @@ -0,0 +1,12 @@ +package ru.tinkoff.edu.java.bot.configuration; + +import jakarta.validation.constraints.NotNull; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +@Validated +@ConfigurationProperties(prefix = "app", ignoreUnknownFields = false) +public record ApplicationConfig(@NotNull String test, + String queueName, + String exchangeName, + String routingKey) {} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java new file mode 100644 index 0000000..d20e877 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java @@ -0,0 +1,66 @@ +package ru.tinkoff.edu.java.bot.configuration; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpStatus; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; +import ru.tinkoff.edu.java.bot.commands.*; +import ru.tinkoff.edu.java.bot.dto.BotCommand; +import ru.tinkoff.edu.java.bot.dto.SetCommandRequest; +import ru.tinkoff.edu.java.bot.telegram.Bot; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; + +@Configuration +@Slf4j +public class BotConfiguration { + + @Value("${tg.bot.token}") + private String token; + + @Value("${tg.api.baseUrl}") + private String tgApiBaseUrl; + + private final HelpCommand helpCommand; + private final StartCommand startCommand; + private final ListCommand listCommand; + private final TrackCommand trackCommand; + private final UntrackCommand untrackCommand; + + public BotConfiguration(HelpCommand helpCommand, StartCommand startCommand, ListCommand listCommand, TrackCommand trackCommand, UntrackCommand untrackCommand) { + this.helpCommand = helpCommand; + this.startCommand = startCommand; + this.listCommand = listCommand; + this.trackCommand = trackCommand; + this.untrackCommand = untrackCommand; + } + + @Bean + public Bot bot() { + EnumMap commands = new EnumMap<>(CommandsEnum.class); + + + commands.put(CommandsEnum.HELP,helpCommand); + commands.put(CommandsEnum.LIST,listCommand); + commands.put(CommandsEnum.START,startCommand); + commands.put(CommandsEnum.TRACK,trackCommand); + commands.put(CommandsEnum.UNTRACK,untrackCommand); + + List apiCommands = new ArrayList<>(commands.values().stream().map(Command::toApiCommand).toList()); + WebClient botConfClient = WebClient.create(tgApiBaseUrl+token); + botConfClient.post().uri("/setMyCommands").bodyValue(new SetCommandRequest(apiCommands)).exchangeToMono(r ->{ + if (!r.statusCode().equals(HttpStatus.OK)){ + log.warn("Похоже, что API Telegram недоступен("); + } + return Mono.empty(); + }).block(); + + return new Bot(token, commands); + } + +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java new file mode 100644 index 0000000..f5d3a09 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java @@ -0,0 +1,27 @@ +package ru.tinkoff.edu.java.bot.configuration; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.reactive.function.client.WebClient; +import ru.tinkoff.edu.java.bot.client.ScrapperClient; + + +@Configuration +public class ClientConfiguration { + + @Value("${scrapper.baseurl}") + private String scrapperBaseUrl; + + + @Bean + public WebClient webClient(){ + return WebClient.create(scrapperBaseUrl); + } + + //Регистрируем клиентов как бины + @Bean + public ScrapperClient scrapperClient() { + return new ScrapperClient(scrapperBaseUrl); + } +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java new file mode 100644 index 0000000..962ff14 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java @@ -0,0 +1,14 @@ +package ru.tinkoff.edu.java.bot.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import parser.LinkParser; + +@Configuration +public class LinkParserConfiguration { + + @Bean + public LinkParser linkParser(){ + return new LinkParser(); + } +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java new file mode 100644 index 0000000..3f53ca7 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java @@ -0,0 +1,80 @@ +package ru.tinkoff.edu.java.bot.configuration; + +import org.springframework.amqp.core.*; +import org.springframework.amqp.support.converter.ClassMapper; +import org.springframework.amqp.support.converter.DefaultClassMapper; +import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; +import org.springframework.amqp.support.converter.MessageConverter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import ru.tinkoff.edu.java.bot.dto.LinkUpdate; +import ru.tinkoff.edu.java.bot.service.ScrapperQueueListener; +import ru.tinkoff.edu.java.bot.service.UpdateService; + +import java.util.HashMap; +import java.util.Map; + +@Configuration +public class RabbitMQConfiguration { + + private final ApplicationConfig config; + + public RabbitMQConfiguration(ApplicationConfig config) { + this.config = config; + } + + @Bean + Queue queue() { + return QueueBuilder.durable(config.queueName()) + .withArgument("x-dead-letter-exchange", config.exchangeName()) + .withArgument("x-dead-letter-routing-key", config.routingKey() + ".dlq") + .build(); + } + + + @Bean + Queue deadLetterQueue() { + return new Queue(config.queueName() + ".dlq", true); + } + + @Bean + DirectExchange exchange() { + return new DirectExchange(config.exchangeName()); + } + + @Bean + Binding binding(Queue queue, DirectExchange exchange) { + return BindingBuilder.bind(queue).to(exchange).with(config.routingKey()); + } + + @Bean + Binding dlqBinding(Queue deadLetterQueue, DirectExchange exchange) { + return BindingBuilder.bind(deadLetterQueue).to(exchange).with(config.routingKey() + ".dlq"); + } + + @Bean + public ClassMapper classMapper() { + Map> mappings = new HashMap<>(); + mappings.put("ru.tinkoff.edu.java.scrapper.dto.LinkUpdate", LinkUpdate.class); + + DefaultClassMapper classMapper = new DefaultClassMapper(); + classMapper.setTrustedPackages("ru.tinkoff.edu.java.scrapper.dto.*"); + classMapper.setIdClassMapping(mappings); + return classMapper; + } + + @Bean + public MessageConverter jsonMessageConverter(ClassMapper classMapper) { + Jackson2JsonMessageConverter jsonConverter = new Jackson2JsonMessageConverter(); + jsonConverter.setClassMapper(classMapper); + return jsonConverter; + } + + + @Bean + public ScrapperQueueListener scrapperQueueListener(AmqpTemplate rabbitTemplate, UpdateService updateService) { + return new ScrapperQueueListener(rabbitTemplate, updateService); + } + + +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java new file mode 100644 index 0000000..1ff0bee --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java @@ -0,0 +1,6 @@ +package ru.tinkoff.edu.java.bot.dto; + + +public record AddLinkRequest(String link) { + +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java new file mode 100644 index 0000000..d8d6113 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java @@ -0,0 +1,7 @@ +package ru.tinkoff.edu.java.bot.dto; + +public record ApiErrorResponse(String description, String code, String exceptionName, + String exceptionMessage, String[] stacktrace) { + + +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java new file mode 100644 index 0000000..201c5c6 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java @@ -0,0 +1,8 @@ +package ru.tinkoff.edu.java.bot.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; + +public record BotCommand(@JsonProperty("command") String command, @JsonProperty("description") String description) implements Serializable { + +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java new file mode 100644 index 0000000..2ab0a84 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java @@ -0,0 +1,10 @@ +package ru.tinkoff.edu.java.bot.dto; + +import java.net.URI; + +public record Link (Long id, URI url){ + @Override + public String toString() { + return "Link{" + "id=" + id + ", url='" + url + '\'' +'}'; + } +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java new file mode 100644 index 0000000..396f750 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java @@ -0,0 +1,11 @@ +package ru.tinkoff.edu.java.bot.dto; + +import java.net.URI; + +public record LinkResponse(long id, URI url) { + + @Override + public String toString() { + return "LinkResponse{" + "id=" + id + ", url=" + url +'}'; + } +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java new file mode 100644 index 0000000..8a92e00 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java @@ -0,0 +1,5 @@ +package ru.tinkoff.edu.java.bot.dto; + +public record LinkUpdate(Long id, String url, String description, Long[] tgChatIds) { + +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java new file mode 100644 index 0000000..5d23d7b --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java @@ -0,0 +1,6 @@ +package ru.tinkoff.edu.java.bot.dto; + +import java.util.List; + +public record ListLinkResponse(List links, int size) { +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java new file mode 100644 index 0000000..7e58ba4 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java @@ -0,0 +1,5 @@ +package ru.tinkoff.edu.java.bot.dto; + +public record RemoveLinkRequest(String link) { + +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java new file mode 100644 index 0000000..799cdc3 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java @@ -0,0 +1,7 @@ +package ru.tinkoff.edu.java.bot.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; + +public record SetCommandRequest(@JsonProperty("commands") List commands) { +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java new file mode 100644 index 0000000..d21ec6a --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java @@ -0,0 +1,8 @@ +package ru.tinkoff.edu.java.bot.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public record UserAddDto(@JsonProperty("username") String username, + @JsonProperty("first_name") String firstName, + @JsonProperty("last_name") String lastName) { +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java new file mode 100644 index 0000000..524f6f3 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java @@ -0,0 +1,10 @@ +package ru.tinkoff.edu.java.bot.exceptions; + +public class ChatNotFoundException extends RuntimeException { + public ChatNotFoundException() { + } + + public ChatNotFoundException(String message) { + super(message); + } +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java new file mode 100644 index 0000000..98c36ae --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java @@ -0,0 +1,10 @@ +package ru.tinkoff.edu.java.bot.exceptions; + +public class LinkIsNotRegisteredToChatException extends RuntimeException { + public LinkIsNotRegisteredToChatException() { + } + + public LinkIsNotRegisteredToChatException(String message) { + super(message); + } +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java new file mode 100644 index 0000000..604e19c --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java @@ -0,0 +1,30 @@ +package ru.tinkoff.edu.java.bot.rest; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import ru.tinkoff.edu.java.bot.dto.LinkUpdate; +import ru.tinkoff.edu.java.bot.service.UpdateService; +import ru.tinkoff.edu.java.bot.service.UpdateServiceImpl; + +@RestController +@Slf4j +public class BotRestController { + + + private final UpdateService updateService; + + + public BotRestController(UpdateService updateService) { + this.updateService = updateService; + } + + @PostMapping("updates") + public void sendUpdate(@RequestBody LinkUpdate request) { + log.info("Пришёл запрос на обновление: "+request); + updateService.updateLink(request); + } + + +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java new file mode 100644 index 0000000..cf4a7ae --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java @@ -0,0 +1,32 @@ +package ru.tinkoff.edu.java.bot.service; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import ru.tinkoff.edu.java.bot.dto.LinkUpdate; + +@RabbitListener(queues = "${app.queue-name}") +@Slf4j +public class ScrapperQueueListener { + + + private final AmqpTemplate rabbitTemplate; + + private final UpdateService updateService; + + + public ScrapperQueueListener(AmqpTemplate rabbitTemplate, UpdateService updateService) { + this.rabbitTemplate = rabbitTemplate; + this.updateService = updateService; + } + + @RabbitHandler + public void receiver(LinkUpdate update) { + log.info("Сообщение об обновлении получено: "+update); +// throw new RuntimeException("test exception"); + updateService.updateLink(update); + } + + +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java new file mode 100644 index 0000000..ed22af0 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java @@ -0,0 +1,8 @@ +package ru.tinkoff.edu.java.bot.service; + +import ru.tinkoff.edu.java.bot.dto.LinkUpdate; + +public interface UpdateService { + +void updateLink(LinkUpdate linkUpdate); +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java new file mode 100644 index 0000000..f3878a4 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java @@ -0,0 +1,26 @@ +package ru.tinkoff.edu.java.bot.service; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import ru.tinkoff.edu.java.bot.dto.LinkUpdate; +import ru.tinkoff.edu.java.bot.telegram.Bot; + +@Service +@Slf4j +public class UpdateServiceImpl implements UpdateService{ + + private final Bot bot; + + public UpdateServiceImpl(Bot bot) { + this.bot = bot; + } + + public void updateLink(LinkUpdate linkUpdate) { + log.info("updateLink() method invocation in UpdateServiceImpl"); + String message = "Вышло обновление по ссылке "+linkUpdate.url()+" \n"+linkUpdate.description(); + for (Long chatId : linkUpdate.tgChatIds()) { + bot.sendMessage(chatId, message); + } + } + +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java new file mode 100644 index 0000000..50c8671 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java @@ -0,0 +1,53 @@ +package ru.tinkoff.edu.java.bot.telegram; + +import com.pengrad.telegrambot.TelegramBot; +import com.pengrad.telegrambot.UpdatesListener; +import com.pengrad.telegrambot.model.Update; +import com.pengrad.telegrambot.request.SendMessage; +import jakarta.annotation.PostConstruct; +import ru.tinkoff.edu.java.bot.commands.Command; +import ru.tinkoff.edu.java.bot.commands.CommandsEnum; + +import java.util.EnumMap; + +public class Bot implements AutoCloseable { + + private final TelegramBot bot; + private final UserMessageProcessor userMessageProcessor; + + + + @PostConstruct + public void init(){ + start(); + } + + public Bot(String token, EnumMap commands) { + System.out.println("Создание бота... Токен: " + token); + userMessageProcessor = new UserMessageProcessor(commands); + bot = new TelegramBot(token); + } + + public void start() { + System.out.println("Бот запущен..."); + bot.setUpdatesListener(updates -> { + for (Update update : updates) { + bot.execute(new SendMessage(update.message().chat().id(), userMessageProcessor.process(update))); + + } + return UpdatesListener.CONFIRMED_UPDATES_ALL; + }); + } + + + public void sendMessage(Long chatId, String msg) { + bot.execute(new SendMessage(chatId, msg)); + } + + + + @Override + public void close() throws Exception { + bot.removeGetUpdatesListener(); + } +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java new file mode 100644 index 0000000..fb08682 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java @@ -0,0 +1,67 @@ +package ru.tinkoff.edu.java.bot.telegram; + +import com.pengrad.telegrambot.model.Update; +import ru.tinkoff.edu.java.bot.commands.*; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; + + +public class UserMessageProcessor { + + private final Map userStateMap; + + private final EnumMap commands; + + + public UserMessageProcessor(EnumMap commands) { + this.commands = commands; + userStateMap = new HashMap<>(); + } + + public String process(Update update) { + Command command; + + + userStateMap.putIfAbsent(update.message().chat().id(), UserState.TYPING_COMMAND); + switch (userStateMap.get(update.message().chat().id())) { + case TYPING_TRACKED -> { + userStateMap.put(update.message().chat().id(), UserState.TYPING_COMMAND); + return commands.get(CommandsEnum.valueOfLabel("/track")).handle(update); + } + case TYPING_UNTRACKED -> { + userStateMap.put(update.message().chat().id(), UserState.TYPING_COMMAND); + return commands.get(CommandsEnum.valueOfLabel("/untrack")).handle(update); + } + case TYPING_COMMAND -> { + userStateMap.put(update.message().chat().id(), UserState.TYPING_COMMAND); + command = commands.get(CommandsEnum.valueOfLabel(update.message().text())); + if (command == null) + return "Неизвестная команда. Нажмите 'Меню' чтобы посмотреть список доступных команд"; + if (command instanceof TrackCommand) { + userStateMap.put(update.message().chat().id(), UserState.TYPING_TRACKED); + return "Отправьте ссылку, которую хотите начать отслеживать"; + } + if (command instanceof UntrackCommand) { + userStateMap.put(update.message().chat().id(), UserState.TYPING_UNTRACKED); + return "Отправьте ссылку, которую хотите перестать отслеживать"; + } + if (command instanceof HelpCommand){ + StringBuilder text = new StringBuilder(); + for (Command c : commands.values()) { + text.append(c.command()).append(" - ").append(c.description()).append("\n"); + } + return text.toString(); + } + return command.handle(update); + } + default -> { + + return "Что-то пошло не так. Проблема на нашеё стороне"; + } + } + + } + + +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java new file mode 100644 index 0000000..70bc584 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java @@ -0,0 +1,5 @@ +package ru.tinkoff.edu.java.bot.telegram; + +public enum UserState { + TYPING_COMMAND, TYPING_TRACKED, TYPING_UNTRACKED +} diff --git a/FP/bot/src/main/resources/application.properties b/FP/bot/src/main/resources/application.properties new file mode 100644 index 0000000..9f20e72 --- /dev/null +++ b/FP/bot/src/main/resources/application.properties @@ -0,0 +1,13 @@ +app.test=beamer-bot +server.port=8080 +springdoc.swagger-ui.path=/swagger-ui +tg.bot.token=${TGBOTTOKEN} +tg.api.baseUrl=https://api.telegram.org/bot +spring.rabbitmq.host=localhost +spring.rabbitmq.port=5672 +spring.rabbitmq.username=romanova +spring.rabbitmq.password=12345654321 +spring.rabbitmq.listener.simple.default-requeue-rejected=false +app.queue-name=scrapper-bot-queue +app.exchange-name=scrapper-bot-exchange +app.routing-key=scrapper-bot-key \ No newline at end of file diff --git a/FP/bot/src/test/java/bot/BotTest.java b/FP/bot/src/test/java/bot/BotTest.java new file mode 100644 index 0000000..af954d2 --- /dev/null +++ b/FP/bot/src/test/java/bot/BotTest.java @@ -0,0 +1,123 @@ +package bot; + +import com.pengrad.telegrambot.model.Chat; +import com.pengrad.telegrambot.model.Message; +import com.pengrad.telegrambot.model.Update; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.test.util.ReflectionTestUtils; +import ru.tinkoff.edu.java.bot.client.ScrapperClient; +import ru.tinkoff.edu.java.bot.commands.Command; +import ru.tinkoff.edu.java.bot.commands.CommandsEnum; +import ru.tinkoff.edu.java.bot.commands.ListCommand; +import ru.tinkoff.edu.java.bot.dto.Link; +import ru.tinkoff.edu.java.bot.dto.ListLinkResponse; +import ru.tinkoff.edu.java.bot.telegram.UserMessageProcessor; +import ru.tinkoff.edu.java.bot.telegram.UserState; + +import java.net.URI; +import java.util.*; + +public class BotTest { + + static UserMessageProcessor userMessageProcessor; + + static ScrapperClient scrapperClient; + + static Update updateForListCommand; + static Update updateForInvalidCommand; + static Message messageForListCommand; + static Message messageForInvalidCommand; + + static Chat chat; + + @BeforeAll + static void init() { + //инициализируем заглушки и входные дынные, т.к. у Update в нет сеттеров, то используем рефлексию, + //чтобы поместить туда нужный Message + scrapperClient = Mockito.mock(ScrapperClient.class); + updateForListCommand = new Update(); + messageForListCommand = new Message(); + chat = new Chat(); + ReflectionTestUtils.setField(chat, "id", 42L); + ReflectionTestUtils.setField(messageForListCommand, "chat", chat); + ReflectionTestUtils.setField(messageForListCommand, "text", "/list"); + ReflectionTestUtils.setField(updateForListCommand, "message", messageForListCommand); + + updateForInvalidCommand = new Update(); + messageForInvalidCommand = new Message(); + + ReflectionTestUtils.setField(messageForInvalidCommand, "chat", chat); + ReflectionTestUtils.setField(messageForInvalidCommand, "text", "Azazelo"); + ReflectionTestUtils.setField(updateForInvalidCommand, "message", messageForInvalidCommand); + } + + @Test + @DisplayName("Тест команды /list, когда список ссылок непустой") + public void listCommandTestNotEmpty() { + + //имитируем нужное поведение клиента для Scrapper, т.к. реального запроса на Scrapper во время не происходит + List listLink = new ArrayList<>(); + listLink.add(new Link(1L, URI.create("https://github.com/lwbeamer/asm-like-language"))); + listLink.add(new Link(2L, URI.create("https://stackoverflow.com/questions/512877/why-cant-i-define-a-static-method-in-a-java-interface"))); + Mockito.when(scrapperClient.getLinks(42L)).thenReturn( + new ListLinkResponse(listLink, listLink.size()) + ); + + EnumMap map = new EnumMap<>(CommandsEnum.class); + map.put(CommandsEnum.LIST, new ListCommand(scrapperClient)); + + userMessageProcessor = new UserMessageProcessor(map); + + String expectedMessage = """ + Ссылок отслеживается - 2 + + https://github.com/lwbeamer/asm-like-language + + https://stackoverflow.com/questions/512877/why-cant-i-define-a-static-method-in-a-java-interface + + """; + + Assertions.assertEquals(expectedMessage, userMessageProcessor.process(updateForListCommand)); + } + + + @Test + @DisplayName("Тест команды /list, когда список ссылок пустой") + public void listCommandTestEmpty() { + Mockito.when(scrapperClient.getLinks(42L)).thenReturn( + new ListLinkResponse(new ArrayList<>(), 0) + ); + + + EnumMap map = new EnumMap<>(CommandsEnum.class); + map.put(CommandsEnum.LIST, new ListCommand(scrapperClient)); + + userMessageProcessor = new UserMessageProcessor(map); + + + String expectedMessage = "Список отслеживаемых ссылок пуст!"; + + Assertions.assertEquals(expectedMessage, userMessageProcessor.process(updateForListCommand)); + } + + @Test + @DisplayName("Тест для проверки ввода неизвестной команды") + public void invalidCommandCheck() { + userMessageProcessor = new UserMessageProcessor(new EnumMap<>(CommandsEnum.class)); + + //Устанавливаем состояние перед тестом - пользователь в сосвтоянии "печатает команду" + Map userStateMap = new HashMap<>(); + userStateMap.put(chat.id(), UserState.TYPING_COMMAND); + ReflectionTestUtils.setField(userMessageProcessor, "userStateMap", userStateMap); + + String expectedMessage = "Неизвестная команда. Нажмите 'Меню' чтобы посмотреть список доступных команд"; + + Assertions.assertEquals(expectedMessage, userMessageProcessor.process(updateForInvalidCommand)); + + } + +} \ No newline at end of file diff --git a/FP/docker-compose.yml b/FP/docker-compose.yml new file mode 100644 index 0000000..c472659 --- /dev/null +++ b/FP/docker-compose.yml @@ -0,0 +1,60 @@ +services: + postgresql: + image: postgres:15 + container_name: postgresql + ports: + - 5432:5432 + environment: + - POSTGRES_USER=lwbeamer + - POSTGRES_PASSWORD=2281337 + - POSTGRES_DB=scrapper + volumes: + - link-service-data:/var/lib/postgresql/data + networks: + - backend + + liquibase-migrations: + image: liquibase/liquibase:4.18 + depends_on: + - postgresql + command: + - --hub-mode=off + - --changelog-file=master.xml + - --driver=org.postgresql.Driver + - --url=jdbc:postgresql://postgresql:5432/scrapper + - --username=romanova + - --password=12345654321 + - update + volumes: + - ./migrations:/liquibase/changelog + networks: + - backend + +volumes: + link-service-data: + +networks: + backend: + name: backend + rabbit: + image: rabbitmq:3-management + hostname: rabbitmq + container_name: rabbit + ports: + - 15672:15672 + - 5672:5672 + environment: + - RABBITMQ_DEFAULT_USER=romanova + - RABBITMQ_DEFAULT_PASS=12345654321 + volumes: + - rabbitmq-state:/var/lib/rabbitmq + networks: + - backend + +volumes: + link-service-data: + rabbitmq-state: + +networks: + backend: + name: backend \ No newline at end of file diff --git a/FP/link-parser/.classpath b/FP/link-parser/.classpath new file mode 100644 index 0000000..a08fc4f --- /dev/null +++ b/FP/link-parser/.classpath @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FP/link-parser/.gitignore b/FP/link-parser/.gitignore new file mode 100644 index 0000000..b83d222 --- /dev/null +++ b/FP/link-parser/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/FP/link-parser/.project b/FP/link-parser/.project new file mode 100644 index 0000000..dec0f32 --- /dev/null +++ b/FP/link-parser/.project @@ -0,0 +1,23 @@ + + + link-parser + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/FP/link-parser/.settings/org.eclipse.core.resources.prefs b/FP/link-parser/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..29abf99 --- /dev/null +++ b/FP/link-parser/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding//src/test/resources=UTF-8 +encoding/=UTF-8 diff --git a/FP/link-parser/.settings/org.eclipse.jdt.core.prefs b/FP/link-parser/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..5e4ec05 --- /dev/null +++ b/FP/link-parser/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/FP/link-parser/.settings/org.eclipse.m2e.core.prefs b/FP/link-parser/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/FP/link-parser/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/FP/link-parser/pom.xml b/FP/link-parser/pom.xml new file mode 100644 index 0000000..3cfd292 --- /dev/null +++ b/FP/link-parser/pom.xml @@ -0,0 +1,30 @@ + + 4.0.0 + + project + project + 0.0.1-SNAPSHOT + + link-parser + + + org.junit.jupiter + junit-jupiter-params + + + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + + + + \ No newline at end of file diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/GitHub_Link.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/GitHub_Link.java new file mode 100644 index 0000000..e244c93 --- /dev/null +++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/GitHub_Link.java @@ -0,0 +1,5 @@ +package ru.tinkoff.edu.java.link_parser.link; + +public record GitHub_Link(String username, String repository) implements Parser_Link { + +} \ No newline at end of file diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/Parser_Link.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/Parser_Link.java new file mode 100644 index 0000000..75db93c --- /dev/null +++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/Parser_Link.java @@ -0,0 +1,5 @@ +package ru.tinkoff.edu.java.link_parser.link; + +public sealed interface Parser_Link permits GitHub_Link, StackOverflow_Link { + +} \ No newline at end of file diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/StackOverflow_Link.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/StackOverflow_Link.java new file mode 100644 index 0000000..1dad8ad --- /dev/null +++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/StackOverflow_Link.java @@ -0,0 +1,5 @@ +package ru.tinkoff.edu.java.link_parser.link; + +public record StackOverflow_Link(long id) implements Parser_Link { + +} \ No newline at end of file diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java new file mode 100644 index 0000000..f3641fc --- /dev/null +++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java @@ -0,0 +1,27 @@ +package ru.tinkoff.edu.java.link_parser.parser; + +import ru.tinkoff.edu.java.link_parser.link.Parser_Link; +import java.net.MalformedURLException; +import java.net.URL; + +public abstract class Abstract { + + Abstract nextParser; + + public Abstract(Abstract nextParser) { + this.nextParser = nextParser; + } + + public abstract Parser_Link parser_Link(String url); + + public final URL tweakUrl(String urlString) { + URL url; + try{ + url = new URL(urlString); + } catch (MalformedURLException e){ + System.out.println("Incorrect URL"); + return null; + } + return url; + } +} \ No newline at end of file diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java new file mode 100644 index 0000000..13ae325 --- /dev/null +++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java @@ -0,0 +1,31 @@ +package ru.tinkoff.edu.java.link_parser.parser; + +import ru.tinkoff.edu.java.link_parser.link.GitHub_Link; +import ru.tinkoff.edu.java.link_parser.link.Parser_Link; + +import java.net.URL; + + +public class Github extends Abstract { + public Github(Abstract nextParser) { + super(nextParser); + } + + @Override + public Parser_Link parser_Link(String url) { + URL toParse = tweakUrl(url); + if (toParse == null) return null; + + if (toParse.getHost().equals("github.com")) { + String[] tokens = toParse.getFile().substring(1).split("/"); + if (tokens.length >= 2) { + return new GitHub_Link(tokens[0], tokens[1]); + } else return null; + } + + + if (nextParser != null) return nextParser.parser_Link(url); + + return null; + } +} \ No newline at end of file diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Link_Parser.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Link_Parser.java new file mode 100644 index 0000000..fac1e3f --- /dev/null +++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Link_Parser.java @@ -0,0 +1,16 @@ +package ru.tinkoff.edu.java.link_parser.parser; + +import ru.tinkoff.edu.java.link_parser.parser.Abstract; +import ru.tinkoff.edu.java.link_parser.parser.Github; +import ru.tinkoff.edu.java.link_parser.parser.StackOverflow; +import ru.tinkoff.edu.java.link_parser.link.Parser_Link; + +public class Link_Parser { + public Parser_Link parseUrl(String url) { + Abstract parser1 = new Github(null); + Abstract parser2 = new StackOverflow(parser1); + + return parser2.parser_Link(url); + } + +} diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java new file mode 100644 index 0000000..e224578 --- /dev/null +++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java @@ -0,0 +1,34 @@ +package ru.tinkoff.edu.java.link_parser.parser; + +import ru.tinkoff.edu.java.link_parser.link.Parser_Link; +import ru.tinkoff.edu.java.link_parser.link.StackOverflow_Link; +import java.net.URL; +public class StackOverflow extends Abstract { + public StackOverflow(Abstract nextParser) { + super(nextParser); + } + + @Override + public Parser_Link parser_Link(String url) { + + URL toParse = tweakUrl(url); + if (toParse == null) return null; + + + if (toParse.getHost().equals("stackoverflow.com")) { + String[] tokens = toParse.getFile().substring(1).split("/"); + if (tokens.length >= 2 && tokens[0].equals("questions")) { + try { + return new StackOverflow_Link(Long.parseLong(tokens[1])); + } catch (NumberFormatException e) { + System.out.println("Incorrect question ID"); + return null; + } + } else return null; + } + + if (nextParser != null) return nextParser.parser_Link(url); + + return null; + } +} \ No newline at end of file diff --git a/FP/link-parser/src/test/java/LinkParserTest.java b/FP/link-parser/src/test/java/LinkParserTest.java new file mode 100644 index 0000000..bef7512 --- /dev/null +++ b/FP/link-parser/src/test/java/LinkParserTest.java @@ -0,0 +1,99 @@ +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import ru.tinkoff.edu.java.link_parser.parser.*; +import ru.tinkoff.edu.java.link_parser.link.*; + +public class LinkParserTest { + + static String validGitHubLink; + static String validStackOverflowLink; + static String gitHubNotRepoLink; + static String stackOverflowNotQuestionLink; + static String emptyLink; + static String withoutProtocolLink; + static String unknownHostLink; + static String invalidLink; + + + @BeforeAll + static void init() { + validGitHubLink = "https://github.com/lwbeamer/asm-like-language"; + validStackOverflowLink = "https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file"; + gitHubNotRepoLink = "https://github.com/issues"; + stackOverflowNotQuestionLink = "https://stackoverflow.co/talent"; + emptyLink = ""; + withoutProtocolLink = "github.com/lwbeamer/asm-like-language"; + unknownHostLink = "https://vk.com/feed"; + invalidLink = "somethingNotValid"; + } + + + @Test + @DisplayName("Тест для проверки валидной ссылки с GitHub") + void checkValidGitHubLink() { + Link_Parser parser = new Link_Parser(); + Assertions.assertEquals(new GitHub_Link("lwbeamer", "asm-like-language"), parser.parseUrl(validGitHubLink), "Тест не пройден, проверьте реузультат"); + } + + + @Test + @DisplayName("Тест для проверки валидной ссылки со StackOverflow") + void validStackOverflowLink() { + Link_Parser parser = new Link_Parser(); + Assertions.assertEquals(new StackOverflow_Link(2336692), parser.parseUrl(validStackOverflowLink), "Тест не пройден, проверьте реузультат"); + } + + + @Test + @DisplayName("Тест для проверки ссылки с GitHub, не являющейся репозиторием") + void gitHubNotRepoLink() { + Link_Parser parser = new Link_Parser(); + Assertions.assertNull(parser.parseUrl(gitHubNotRepoLink), "Тест не пройден, проверьте реузультат"); + } + + @Test + @DisplayName("Тест для проверки ссылки со StackOverflow, не являющейся вопросом") + void stackOverflowNotQuestionLink() { + Link_Parser parser = new Link_Parser(); + Assertions.assertNull(parser.parseUrl(stackOverflowNotQuestionLink), "Тест не пройден, проверьте реузультат"); + } + + + @Test + @DisplayName("Тест для проверки пустой ссылки") + void emptyLink() { + Link_Parser parser = new Link_Parser(); + Assertions.assertNull(parser.parseUrl(emptyLink), "Тест не пройден, проверьте реузультат"); + } + + + @Test + @DisplayName("Тест для проверки ссылки без указания протокола") + void withoutProtocolLink() { + Link_Parser parser = new Link_Parser(); + Assertions.assertNull(parser.parseUrl(withoutProtocolLink), "Тест не пройден, проверьте реузультат"); + } + + @Test + @DisplayName("Тест для проверки ссылки, не относящейся к отслеживаемым ресурсам") + void unknownHostLink() { + Link_Parser parser = new Link_Parser(); + Assertions.assertNull(parser.parseUrl(unknownHostLink), "Тест не пройден, проверьте реузультат"); + } + + + @Test + @DisplayName("Тест для проверки непустой невалидной ссылки") + void invalidLink() { + Link_Parser parser = new Link_Parser(); + Assertions.assertNull(parser.parseUrl(invalidLink), "Тест не пройден, проверьте реузультат"); + } + + +} diff --git a/FP/migrations/01-schema-1.sql b/FP/migrations/01-schema-1.sql new file mode 100644 index 0000000..838947b --- /dev/null +++ b/FP/migrations/01-schema-1.sql @@ -0,0 +1,11 @@ +--liquibase formatted sql + +--changeset romanova:create-user-table-1 +CREATE TABLE "user" ( + chat_id bigint PRIMARY KEY, + username text UNIQUE NOT NULL, + first_name text, + last_name text +); + +--rollback DROP TABLE "user"; \ No newline at end of file diff --git a/FP/migrations/02-schema-2.sql b/FP/migrations/02-schema-2.sql new file mode 100644 index 0000000..0e40afb --- /dev/null +++ b/FP/migrations/02-schema-2.sql @@ -0,0 +1,15 @@ +--liquibase formatted sql + +--changeset romanova:create-link-table-1 +CREATE TABLE "link" ( + id bigserial PRIMARY KEY, + url text UNIQUE NOT NULL, + checked_at timestamp NOT NULL, + gh_pushed_at timestamp, + gh_description text, + gh_forks_count int, + so_answer_count int, + so_last_edit_date timestamp +); + +--rollback DROP TABLE "link"; \ No newline at end of file diff --git a/FP/migrations/03-schema-3.sql b/FP/migrations/03-schema-3.sql new file mode 100644 index 0000000..c407b73 --- /dev/null +++ b/FP/migrations/03-schema-3.sql @@ -0,0 +1,10 @@ +--liquibase formatted sql + +--changeset romanova:create-user-link-table-1 +CREATE TABLE "user_link" ( + link_id bigint REFERENCES "link" (id), + chat_id bigint REFERENCES "user" (chat_id), + PRIMARY KEY (link_id,chat_id) +); + +--rollback DROP TABLE "user_link"; \ No newline at end of file diff --git a/FP/migrations/create.sql b/FP/migrations/create.sql new file mode 100644 index 0000000..a4e2a68 --- /dev/null +++ b/FP/migrations/create.sql @@ -0,0 +1,18 @@ +create table "user" ( + chat_id bigint primary key, + username text unique not null, + first_name text, + last_name text +); + +create table "link" ( + id bigserial primary key, + url text unique not null, + updated_at timestamp not null +); + +create table "user_link" ( + link_id bigint references "link" (id), + chat_id bigint references "user" (chat_id), + primary key (link_id,chat_id) +) \ No newline at end of file diff --git a/FP/migrations/delete.sql b/FP/migrations/delete.sql new file mode 100644 index 0000000..1fb56bd --- /dev/null +++ b/FP/migrations/delete.sql @@ -0,0 +1,3 @@ +drop table "user_link"; +drop table "user"; +drop table "link"; \ No newline at end of file diff --git a/FP/migrations/insert.sql b/FP/migrations/insert.sql new file mode 100644 index 0000000..30b59be --- /dev/null +++ b/FP/migrations/insert.sql @@ -0,0 +1,37 @@ +insert into "user" (chat_id, username, first_name, last_name) +values (42, 'testUser42', 'test', 'testov'), + (34, 'testUser34', 'test', 'testov'), + (65, 'testUser65', 'test', 'testov'), + (45, 'testUser45', 'test', 'testov'), + (523, 'testUser523', 'test', 'testov'), + (645, 'testUser645', 'test', 'testov'), + (7452, 'testUser7452', 'test', 'testov'), + (44562, 'testUser44562', 'test', 'testov'), + (423452, 'testUser423452', 'test', 'testov'), + (2, 'testUser2', 'test', 'testov'); + +insert into "link" (url, updated_at) +values ('https://stackoverflow.com/questions/14141266/postgresql-foreign-key-on-delete-cascade', '2022-05-19 15:13:27'), + ('https://github.com/linus/doctest','2022-01-31 13:13:50'), + ('https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file','2023-03-27 09:58:45'); + +insert into "user_link" (link_id, chat_id) +values (1,42), + (1,45), + (1,2), + (1,7452), + (2,44562), + (2,423452), + (2,645), + (2,523), + (3,34), + (3,65), + (3,7452), + (3,45), + (4,42), + (4,45), + (4,2), + (4,7452); + + + diff --git a/FP/migrations/master.xml b/FP/migrations/master.xml new file mode 100644 index 0000000..c566afc --- /dev/null +++ b/FP/migrations/master.xml @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/FP/pom.xml b/FP/pom.xml new file mode 100644 index 0000000..a1baa3d --- /dev/null +++ b/FP/pom.xml @@ -0,0 +1,123 @@ + + 4.0.0 + project + project + 0.0.1-SNAPSHOT + pom + + bot + link-parser + scrapper + scrapper-jooq + + + 3.0.1 + 2022.0.0 + 3.10.1 + 23.1.0 + UTF-8 + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + org.junit.jupiter + junit-jupiter-params + ${junit.version} + test + + + org.mockito + mockito-core + ${mockito.version} + test + + + org.testcontainers + testcontainers-bom + ${testcontainers.version} + pom + import + + + org.springframework.boot + spring-boot-starter-test + ${spring.test.version} + test + + + + + + + + org.jetbrains + annotations + ${annotations.version} + provided + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + true + + + + org.projectlombok + lombok + + + + + + + repackage + build-info + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 17 + true + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + + + + \ No newline at end of file diff --git a/FP/scrapper-jooq/.classpath b/FP/scrapper-jooq/.classpath new file mode 100644 index 0000000..ead1d0f --- /dev/null +++ b/FP/scrapper-jooq/.classpath @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FP/scrapper-jooq/.gitignore b/FP/scrapper-jooq/.gitignore new file mode 100644 index 0000000..b83d222 --- /dev/null +++ b/FP/scrapper-jooq/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/FP/scrapper-jooq/.project b/FP/scrapper-jooq/.project new file mode 100644 index 0000000..f320f87 --- /dev/null +++ b/FP/scrapper-jooq/.project @@ -0,0 +1,23 @@ + + + scrapper-jooq + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs b/FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..609d3ca --- /dev/null +++ b/FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +encoding//src/main/resources=UTF-8 +encoding//src/test/resources=UTF-8 +encoding/=UTF-8 diff --git a/FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs b/FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..5e4ec05 --- /dev/null +++ b/FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs b/FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/FP/scrapper-jooq/pom.xml b/FP/scrapper-jooq/pom.xml new file mode 100644 index 0000000..b6f0785 --- /dev/null +++ b/FP/scrapper-jooq/pom.xml @@ -0,0 +1,40 @@ + + 4.0.0 + + project + project + 0.0.1-SNAPSHOT + + scrapper-jooq + + 17 + 17 + UTF-8 + + + + + org.springframework.boot + spring-boot-starter-jooq + + + org.jooq + jooq-codegen + + + org.jooq + jooq-meta-extensions-liquibase + 3.18.3 + + + org.jooq + jooq-postgres-extensions + 3.18.3 + + + org.liquibase + liquibase-core + + + + \ No newline at end of file diff --git a/FP/scrapper-jooq/src/main/java/JooqCodegen.java b/FP/scrapper-jooq/src/main/java/JooqCodegen.java new file mode 100644 index 0000000..ee35d24 --- /dev/null +++ b/FP/scrapper-jooq/src/main/java/JooqCodegen.java @@ -0,0 +1,49 @@ +import org.jooq.codegen.GenerationTool; +import org.jooq.meta.jaxb.Configuration; +import org.jooq.meta.jaxb.Database; +import org.jooq.meta.jaxb.Generate; +import org.jooq.meta.jaxb.Generator; +import org.jooq.meta.jaxb.Property; +import org.jooq.meta.jaxb.Target; + +public class JooqCodegen { + public static void main(String[] args) throws Exception { + Database database = new Database() + .withName("org.jooq.meta.extensions.liquibase.LiquibaseDatabase") + .withProperties( + new Property().withKey("rootPath").withValue("migrations"), + new Property().withKey("scripts").withValue("master.xml") + ); + + Generate options = new Generate() + .withGeneratedAnnotation(true) + .withGeneratedAnnotationDate(false) + .withNullableAnnotation(true) + .withNullableAnnotationType("org.jetbrains.annotations.Nullable") + .withNonnullAnnotation(true) + .withNonnullAnnotationType("org.jetbrains.annotations.NotNull") + .withJpaAnnotations(false) + .withValidationAnnotations(true) + .withSpringAnnotations(true) + .withConstructorPropertiesAnnotation(true) + .withConstructorPropertiesAnnotationOnPojos(true) + .withConstructorPropertiesAnnotationOnRecords(true) + .withFluentSetters(false) + .withDaos(false) + .withPojos(true); + + Target target = new Target() + .withPackageName("ru.tinkoff.edu.java.scrapper.domain.jooq") + .withDirectory("scrapper/src/main/java"); + + Configuration configuration = new Configuration() + .withGenerator( + new Generator() + .withDatabase(database) + .withGenerate(options) + .withTarget(target) + ); + + GenerationTool.generate(configuration); + } +} \ No newline at end of file diff --git a/FP/scrapper/.classpath b/FP/scrapper/.classpath new file mode 100644 index 0000000..a08fc4f --- /dev/null +++ b/FP/scrapper/.classpath @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FP/scrapper/.gitignore b/FP/scrapper/.gitignore new file mode 100644 index 0000000..b83d222 --- /dev/null +++ b/FP/scrapper/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/FP/scrapper/.project b/FP/scrapper/.project new file mode 100644 index 0000000..d56fd66 --- /dev/null +++ b/FP/scrapper/.project @@ -0,0 +1,23 @@ + + + scrapper + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/FP/scrapper/.settings/org.eclipse.core.resources.prefs b/FP/scrapper/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..29abf99 --- /dev/null +++ b/FP/scrapper/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding//src/test/resources=UTF-8 +encoding/=UTF-8 diff --git a/FP/scrapper/.settings/org.eclipse.jdt.core.prefs b/FP/scrapper/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..5e4ec05 --- /dev/null +++ b/FP/scrapper/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/FP/scrapper/.settings/org.eclipse.m2e.core.prefs b/FP/scrapper/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/FP/scrapper/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/FP/scrapper/pom.xml b/FP/scrapper/pom.xml new file mode 100644 index 0000000..1b0c4fa --- /dev/null +++ b/FP/scrapper/pom.xml @@ -0,0 +1,120 @@ + + + 4.0.0 + + project + project + 0.0.1-SNAPSHOT + + + scrapper + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-webflux + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.springframework + spring-context-indexer + true + + + org.projectlombok + lombok + true + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.0.2 + + + ru.tinkoff.edu + link-parser + 1.0-SNAPSHOT + + + org.testcontainers + junit-jupiter + test + + + org.springframework.boot + spring-boot-starter-test + + + org.testcontainers + postgresql + test + + + org.liquibase + liquibase-core + test + + + org.springframework.boot + spring-boot-starter-jdbc + + + org.postgresql + postgresql + runtime + + + org.jooq + jooq + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-amqp + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-failsafe-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + + + \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java new file mode 100644 index 0000000..fef7338 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java @@ -0,0 +1,22 @@ +package ru.tinkoff.edu.java.scrapper; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import ru.tinkoff.edu.java.scrapper.configuration.ApplicationConfig; +import org.springframework.scheduling.annotation.EnableScheduling; +import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity; +import ru.tinkoff.edu.java.scrapper.configuration.ApplicationConfig; +import ru.tinkoff.edu.java.scrapper.service.jpa.impl.JpaSubscriptionServiceImpl; +import ru.tinkoff.edu.java.scrapper.service.jpa.impl.JpaTgChatServiceImpl; + + +@SpringBootApplication +@EnableConfigurationProperties(ApplicationConfig.class) +@EnableScheduling +public class ScrapperApplication { + public static void main(String[] args) { + var ctx = SpringApplication.run(ScrapperApplication.class, args); + ApplicationConfig config = ctx.getBean(ApplicationConfig.class); + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java new file mode 100644 index 0000000..2e1aacf --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java @@ -0,0 +1,33 @@ +package ru.tinkoff.edu.java.scrapper.advice; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.client.HttpClientErrorException; +import ru.tinkoff.edu.java.scrapper.dto.ApiErrorResponse; +import ru.tinkoff.edu.java.scrapper.exception.ChatAlreadyExistException; +import ru.tinkoff.edu.java.scrapper.exception.ChatNotFoundException; +import ru.tinkoff.edu.java.scrapper.exception.LinkIsAlreadyAddedException; +import ru.tinkoff.edu.java.scrapper.exception.LinkNotFoundException; + +import java.util.Arrays; + +@RestControllerAdvice +public class AppExceptionHandler { + + @ExceptionHandler({LinkNotFoundException.class, ChatNotFoundException.class}) + @ResponseStatus(value = HttpStatus.NOT_FOUND) + public ApiErrorResponse handleNotFoundExceptions(RuntimeException exception) { + return new ApiErrorResponse( + "Error", HttpStatus.NOT_FOUND.toString(), exception.getClass().getName(), exception.getMessage(), Arrays.stream(exception.getStackTrace()).map(StackTraceElement::toString).toList().toArray(String[]::new)); + } + + + @ExceptionHandler({ChatAlreadyExistException.class, LinkIsAlreadyAddedException.class}) + @ResponseStatus(value = HttpStatus.BAD_REQUEST) + public ApiErrorResponse handleBadRequestExceptions(RuntimeException exception) { + return new ApiErrorResponse( + "Error", HttpStatus.BAD_REQUEST.toString(), exception.getClass().getName(), exception.getMessage(), Arrays.stream(exception.getStackTrace()).map(StackTraceElement::toString).toList().toArray(String[]::new)); + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java new file mode 100644 index 0000000..021e3ec --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java @@ -0,0 +1,38 @@ +package ru.tinkoff.edu.java.scrapper.client; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; +import ru.tinkoff.edu.java.scrapper.dto.LinkUpdate; +import ru.tinkoff.edu.java.scrapper.exception.BotClientException; +import ru.tinkoff.edu.java.scrapper.service.UpdateNotificationService; + +@Slf4j +public class BotClient { + + @Value("${bot.baseurl}") + private String botBaseUrl; + + private final WebClient webClient; + + public BotClient(WebClient webClient) { + this.webClient = webClient; + } + + public BotClient(String botBaseUrl) { + this.webClient = WebClient.create(botBaseUrl); + } + + public void updateLink(LinkUpdate request) { + log.info("Sending update request to Bot"); + webClient.post().uri("/updates").bodyValue(request).exchangeToMono(r -> { + if (r.statusCode().equals(HttpStatus.BAD_REQUEST)) { + throw new BotClientException("Чат с таким ID не зарегистрирован"); + } + return Mono.empty(); + }).block(); + } + +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java new file mode 100644 index 0000000..156cf35 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java @@ -0,0 +1,47 @@ +package ru.tinkoff.edu.java.scrapper.client; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.reactive.function.client.WebClient; +import ru.tinkoff.edu.java.scrapper.dto.GitHubResponse; +import org.springframework.http.HttpStatus; +import ru.tinkoff.edu.java.scrapper.exception.GitHubRequestException; + +public class GitHubClient { + + + @Value("${gh.baseurl}") + private String gitHubBaseUrl; + + private final WebClient webClient; + + //для использования baseUrl по умолчанию (берётся из properties) + public GitHubClient() { + this.webClient = WebClient.create(gitHubBaseUrl); + } + + + //можно указать базовый URL + public GitHubClient(String baseUrl) { + this.webClient = WebClient.create(baseUrl); + } + + + public GitHubResponse fetchRepo(String owner, String repo) { + GitHubResponse response = webClient.get().uri("/repos/{owner}/{repo}", owner, repo).exchangeToMono(r->{ + if (!r.statusCode().equals(HttpStatus.OK)) throw new GitHubRequestException("Error with request to GH API"); + return r.bodyToMono(GitHubResponse.class); + }).block(); + + return response; + + } + public void strFetchRepo(String owner, String repo){ + String strReponse = webClient.get().uri("/repos/{owner}/{repo}", owner, repo).exchangeToMono(r->{ + if (!r.statusCode().equals(HttpStatus.OK)) throw new GitHubRequestException("Error with request to GH API"); + return r.bodyToMono(String.class); + }).block(); + + System.out.println(strReponse); + + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java new file mode 100644 index 0000000..6651dd9 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java @@ -0,0 +1,44 @@ +package ru.tinkoff.edu.java.scrapper.client; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.http.HttpStatus; +import ru.tinkoff.edu.java.scrapper.dto.StackOverflowItem; +import ru.tinkoff.edu.java.scrapper.dto.StackOverflowResponse; +import ru.tinkoff.edu.java.scrapper.exception.BadResponseFromApiException; +import ru.tinkoff.edu.java.scrapper.dto.GitHubResponse; +import ru.tinkoff.edu.java.scrapper.exception.GitHubRequestException; +import ru.tinkoff.edu.java.scrapper.exception.StackOverflowRequestException; + +public class StackOverflowClient { + + @Value("${so.baseurl}") + private String stackOverflowBaseUrl; + + private final WebClient webClient; + + + //для использования baseUrl по умолчанию (берётся из properties) + public StackOverflowClient() { + this.webClient = WebClient.create(stackOverflowBaseUrl); + } + + + //можно указать базовый URL + public StackOverflowClient(String baseUrl) { + this.webClient = WebClient.create(baseUrl); + } + + public StackOverflowItem fetchQuestion(long id) { + + StackOverflowResponse response = webClient.get().uri("/questions/{id}?order=desc&sort=activity&site=stackoverflow", id).exchangeToMono(r->{ + if (!r.statusCode().equals(HttpStatus.OK)) throw new StackOverflowRequestException("Error with request to SO API"); + return r.bodyToMono(StackOverflowResponse.class); + }).block(); + + if (response == null || response.items().size() == 0) + throw new BadResponseFromApiException("API StackOverflow returned bad response"); + + return response.items().get(0); + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java new file mode 100644 index 0000000..856e54e --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java @@ -0,0 +1,26 @@ +package ru.tinkoff.edu.java.scrapper.configuration; + +import jakarta.validation.constraints.NotNull; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.validation.annotation.Validated; +import ru.tinkoff.edu.java.scrapper.schedule.Scheduler; + +@Validated +@ConfigurationProperties(prefix = "app", ignoreUnknownFields = false) +public record ApplicationConfig(@NotNull String test, + @NotNull Scheduler scheduler, + @NotNull AccessType dataBaseAccessType, + @NotNull Boolean useQueue, + String queueName, + String exchangeName, + String routingKey){ + + @Bean + public long schedulerIntervalMs(ApplicationConfig config) { + return config.scheduler().interval().toMillis(); + } + public enum AccessType { + JDBC, JPA, JOOQ + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java new file mode 100644 index 0000000..8694acf --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java @@ -0,0 +1,44 @@ +package ru.tinkoff.edu.java.scrapper.configuration; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import ru.tinkoff.edu.java.scrapper.client.GitHubClient; +import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient; +import org.springframework.web.reactive.function.client.WebClient; +import ru.tinkoff.edu.java.scrapper.client.BotClient; + +@Configuration +public class ClientConfiguration { + + @Value("${gh.baseurl}") + private String gitHubBaseUrl; + + @Value("${so.baseurl}") + private String stackOverflowBaseUrl; + + @Value("${bot.baseurl}") + private String botBaseUrl; + + + //Регистрируем клиентов как бины + @Bean + public GitHubClient gitHubClientService() { + return new GitHubClient(gitHubBaseUrl); + } + + @Bean + public StackOverflowClient stackOverflowClientService() { + return new StackOverflowClient(stackOverflowBaseUrl); + } + @Bean + public WebClient ghWebClient(){ + return WebClient.create(gitHubBaseUrl); + } + + @Bean + public WebClient soWebClient(){ + return WebClient.create(stackOverflowBaseUrl); + } + +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java new file mode 100644 index 0000000..df6780e --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java @@ -0,0 +1,28 @@ +package ru.tinkoff.edu.java.scrapper.configuration; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.reactive.function.client.WebClient; +import ru.tinkoff.edu.java.scrapper.client.BotClient; + +@Configuration +@ConditionalOnProperty(prefix = "app", name = "use-queue", havingValue = "false") +public class HTTPConfiguration { + + @Value("${bot.baseurl}") + private String botBaseUrl; + + + @Bean + public BotClient botClient(){return new BotClient(botBaseUrl);} + + @Bean + public WebClient botWebClient(){ + return WebClient.create(botBaseUrl); + } + + + +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java new file mode 100644 index 0000000..e400f15 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java @@ -0,0 +1,14 @@ +package ru.tinkoff.edu.java.scrapper.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import ru.tinkoff.edu.java.link_parser.parser.Link_Parser; + +@Configuration +public class LinkParserConfiguration { + + @Bean + public Link_Parser linkParser(){ + return new Link_Parser(); + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java new file mode 100644 index 0000000..d8b1217 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java @@ -0,0 +1,50 @@ +package ru.tinkoff.edu.java.scrapper.configuration; + +import org.springframework.amqp.core.*; +import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; +import org.springframework.amqp.support.converter.MessageConverter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import ru.tinkoff.edu.java.scrapper.service.ScrapperQueueProducer; + +@Configuration +@ConditionalOnProperty(prefix = "app", name = "use-queue", havingValue = "true") +public class RabbitMQConfiguration { + + private final ApplicationConfig config; + + public RabbitMQConfiguration(ApplicationConfig config) { + this.config = config; + } + + @Bean + Queue queue() { + return QueueBuilder.durable(config.queueName()) + .withArgument("x-dead-letter-exchange", config.exchangeName()) + .withArgument("x-dead-letter-routing-key", config.routingKey() + ".dlq") + .build(); + } + + @Bean + DirectExchange exchange() { + return new DirectExchange(config.exchangeName()); + } + + @Bean + Binding binding(Queue queue, DirectExchange exchange) { + return BindingBuilder.bind(queue).to(exchange).with(config.routingKey()); + } + + @Bean + public MessageConverter jsonMessageConverter() { + return new Jackson2JsonMessageConverter(); + } + + + @Bean + public ScrapperQueueProducer scrapperQueueProducer(AmqpTemplate rabbitTemplate) { + return new ScrapperQueueProducer(rabbitTemplate, config); + } + +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java new file mode 100644 index 0000000..d70f747 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java @@ -0,0 +1,99 @@ +package ru.tinkoff.edu.java.scrapper.configuration.database.acess; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; +import ru.tinkoff.edu.java.link_parser.Link_Parser; +import ru.tinkoff.edu.java.scrapper.client.BotClient; +import ru.tinkoff.edu.java.scrapper.client.GitHubClient; +import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient; +import ru.tinkoff.edu.java.scrapper.mapper.LinkRowMapper; +import ru.tinkoff.edu.java.scrapper.mapper.SubscriptionRowMapper; +import ru.tinkoff.edu.java.scrapper.mapper.UserRowMapper; +import ru.tinkoff.edu.java.scrapper.repository.jdbc.LinkJdbcTemplateRepository; +import ru.tinkoff.edu.java.scrapper.repository.jdbc.SubscriptionJdbcTemplateRepository; +import ru.tinkoff.edu.java.scrapper.repository.jdbc.UserJdbcTemplateRepository; +import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.LinkRepository; +import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository; +import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.UserRepository; +import ru.tinkoff.edu.java.scrapper.service.UpdateNotificationService; +import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService; +import ru.tinkoff.edu.java.scrapper.service.contract.SubscriptionService; +import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService; +import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.LinkUpdateServiceImpl; +import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.SubscriptionServiceImpl; +import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.TgChatServiceImpl; + +@Configuration +@ConditionalOnProperty(prefix = "app", name = "database-access-type", havingValue = "jdbc") +public class JdbcAccessConfiguration { + + @Bean + public LinkRowMapper linkRowMapper() { + return new LinkRowMapper(); + } + + @Bean + public SubscriptionRowMapper subscriptionRowMapper() { + return new SubscriptionRowMapper(); + } + + @Bean + public UserRowMapper userRowMapper() { + return new UserRowMapper(); + } + + @Bean + public LinkRepository linkRepository(JdbcTemplate jdbcTemplate, LinkRowMapper linkRowMapper) { + return new LinkJdbcTemplateRepository(jdbcTemplate, linkRowMapper); + } + + @Bean + public SubscriptionRepository subscriptionRepository(JdbcTemplate jdbcTemplate, SubscriptionRowMapper subscriptionRowMapper) { + return new SubscriptionJdbcTemplateRepository(jdbcTemplate, subscriptionRowMapper, linkRowMapper()); + } + + @Bean + public UserRepository userRepository(JdbcTemplate jdbcTemplate, UserRowMapper userRowMapper) { + return new UserJdbcTemplateRepository(jdbcTemplate, userRowMapper); + } + + @Bean + public LinkUpdateService linkUpdateService( + LinkRepository linkRepository, + SubscriptionRepository subscriptionRepository, + Link_Parser linkParser, + GitHubClient gitHubClient, + StackOverflowClient stackOverflowClient, + BotClient botClient + ) { + return new LinkUpdateServiceImpl( + linkRepository, + subscriptionRepository, + linkParser, + gitHubClient, + stackOverflowClient, + botClient); + } + + @Bean + public SubscriptionService subscriptionService( + LinkRepository linkRepository, + SubscriptionRepository subscriptionRepository + ) { + return new SubscriptionServiceImpl( + linkRepository, + subscriptionRepository); + } + + @Bean + public TgChatService tgChatService( + UserRepository userRepository, + SubscriptionRepository subscriptionRepository + ) { + return new TgChatServiceImpl( + userRepository, + subscriptionRepository); + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java new file mode 100644 index 0000000..47864de --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java @@ -0,0 +1,84 @@ +package ru.tinkoff.edu.java.scrapper.configuration.database.acess; + +import org.jooq.DSLContext; +import org.jooq.impl.DSL; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import ru.tinkoff.edu.java.link_parser.Link_Parser; +import ru.tinkoff.edu.java.scrapper.client.BotClient; +import ru.tinkoff.edu.java.scrapper.client.GitHubClient; +import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient; +import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.LinkRepository; +import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository; +import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.UserRepository; +import ru.tinkoff.edu.java.scrapper.repository.jooq.LinkJooqRepository; +import ru.tinkoff.edu.java.scrapper.repository.jooq.SubscriptionJooqRepository; +import ru.tinkoff.edu.java.scrapper.repository.jooq.UserJooqRepository; +import ru.tinkoff.edu.java.scrapper.service.UpdateNotificationService; +import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService; +import ru.tinkoff.edu.java.scrapper.service.contract.SubscriptionService; +import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService; +import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.LinkUpdateServiceImpl; +import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.SubscriptionServiceImpl; +import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.TgChatServiceImpl; +@Configuration +@ConditionalOnProperty(prefix = "app", name = "database-access-type", havingValue = "jooq") +public class JooqAccessConfiguration { + + + @Bean + public LinkRepository linkRepository(DSLContext dslContext){ + return new LinkJooqRepository(dslContext); + } + + @Bean + public SubscriptionRepository subscriptionRepository(DSLContext dslContext){ + return new SubscriptionJooqRepository(dslContext); + } + + + @Bean + public UserRepository userRepository(DSLContext dslContext){ + return new UserJooqRepository(dslContext); + } + + @Bean + public LinkUpdateService linkUpdateService( + LinkRepository linkRepository, + SubscriptionRepository subscriptionRepository, + LinkParser linkParser, + GitHubClient gitHubClient, + StackOverflowClient stackOverflowClient, + BotClient botClient + ) { + return new LinkUpdateServiceImpl( + linkRepository, + subscriptionRepository, + linkParser, + gitHubClient, + stackOverflowClient, + botClient); + } + + @Bean + public SubscriptionService subscriptionService( + LinkRepository linkRepository, + SubscriptionRepository subscriptionRepository + ) { + return new SubscriptionServiceImpl( + linkRepository, + subscriptionRepository); + } + + @Bean + public TgChatService tgChatService( + UserRepository userRepository, + SubscriptionRepository subscriptionRepository + ) { + return new TgChatServiceImpl( + userRepository, + subscriptionRepository); + } + +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java new file mode 100644 index 0000000..ff97aba --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java @@ -0,0 +1,61 @@ +package ru.tinkoff.edu.java.scrapper.configuration.database.acess; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import ru.tinkoff.edu.java.link_parser.Link_Parser; +import ru.tinkoff.edu.java.scrapper.client.BotClient; +import ru.tinkoff.edu.java.scrapper.client.GitHubClient; +import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient; +import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository; +import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.UserRepository; +import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaLinkRepository; +import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaUserRepository; +import ru.tinkoff.edu.java.scrapper.service.UpdateNotificationService; +import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService; +import ru.tinkoff.edu.java.scrapper.service.contract.SubscriptionService; +import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService; +import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.TgChatServiceImpl; +import ru.tinkoff.edu.java.scrapper.service.jpa.impl.JpaLinkUpdateServiceImpl; +import ru.tinkoff.edu.java.scrapper.service.jpa.impl.JpaSubscriptionServiceImpl; +import ru.tinkoff.edu.java.scrapper.service.jpa.impl.JpaTgChatServiceImpl; + +@Configuration +@ConditionalOnProperty(prefix = "app", name = "database-access-type", havingValue = "jpa") +public class JpaAccessConfiguration { + + @Bean + public LinkUpdateService linkUpdateService( + JpaLinkRepository linkRepository, + Link_Parser linkParser, + GitHubClient gitHubClient, + StackOverflowClient stackOverflowClient, + BotClient botClient) { + return new JpaLinkUpdateServiceImpl( + linkRepository, + linkParser, + gitHubClient, + stackOverflowClient, + botClient + ); + } + + @Bean + public SubscriptionService subscriptionService( + JpaLinkRepository linkRepository, + JpaUserRepository userRepository) { + return new JpaSubscriptionServiceImpl( + linkRepository, + userRepository + ); + } + + @Bean + public TgChatService tgChatService( + JpaUserRepository userRepository) { + return new JpaTgChatServiceImpl( + userRepository + ); + } + +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java new file mode 100644 index 0000000..97985ba --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java @@ -0,0 +1,5 @@ +package ru.tinkoff.edu.java.scrapper.dto; + +public record AddLinkRequest(String link) { + +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java new file mode 100644 index 0000000..7c065be --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java @@ -0,0 +1,6 @@ +package ru.tinkoff.edu.java.scrapper.dto; + +public record ApiErrorResponse(String description, String code, String exceptionName, + String exceptionMessage, String[] stacktrace) { + +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java new file mode 100644 index 0000000..8f6367c --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java @@ -0,0 +1,25 @@ +package ru.tinkoff.edu.java.scrapper.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.OffsetDateTime; + +public record GitHubResponse(@JsonProperty("pushed") OffsetDateTime pushedAt, + @JsonProperty("updated") OffsetDateTime updatedAt, + @JsonProperty("full_name") String fullName, + @JsonProperty("description") String description, + @JsonProperty("forks_count") int forksCount +) { + + +@Override +public String toString() { + return "GitHubResponse{" + + "pushedAt=" + pushedAt + + ", updatedAt=" + updatedAt + + ", fullName='" + fullName + '\'' + + ", description='" + description + '\'' + + ", forksCount=" + forksCount + + '}'; +} + +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java new file mode 100644 index 0000000..cadc95f --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java @@ -0,0 +1,5 @@ +package ru.tinkoff.edu.java.scrapper.dto; + +public record LinkResponse(long id, String url) { + +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java new file mode 100644 index 0000000..1b6410a --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java @@ -0,0 +1,5 @@ +package ru.tinkoff.edu.java.scrapper.dto; + +public record LinkUpdate(Long id, String url, String description, Long[] tgChatIds) { + +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java new file mode 100644 index 0000000..a142f3a --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java @@ -0,0 +1,8 @@ +package ru.tinkoff.edu.java.scrapper.dto; + +import ru.tinkoff.edu.java.scrapper.model.Link; +import java.util.List; + +public record ListLinkResponse(List links, int size) { + +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java new file mode 100644 index 0000000..09a3867 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java @@ -0,0 +1,5 @@ +package ru.tinkoff.edu.java.scrapper.dto; + +public record RemoveLinkRequest(String link) { + +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java new file mode 100644 index 0000000..9e2f0b9 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java @@ -0,0 +1,8 @@ +package ru.tinkoff.edu.java.scrapper.dto; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.time.OffsetDateTime; +public record StackOverflowItem(@JsonProperty("last_edit_date") OffsetDateTime lastActivityDate, + @JsonProperty("last_activity_date") OffsetDateTime lastEditDate) { + +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java new file mode 100644 index 0000000..50227fc --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java @@ -0,0 +1,8 @@ +package ru.tinkoff.edu.java.scrapper.dto; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.time.OffsetDateTime; +import java.util.List; +public record StackOverflowResponse(List items) { + +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java new file mode 100644 index 0000000..58d769c --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java @@ -0,0 +1,8 @@ +package ru.tinkoff.edu.java.scrapper.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public record UserAddDto(@JsonProperty("username") String username, + @JsonProperty("first_name") String firstName, + @JsonProperty("last_name") String lastName) { +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java new file mode 100644 index 0000000..d5be7a4 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java @@ -0,0 +1,12 @@ +package ru.tinkoff.edu.java.scrapper.exception; + +public class BadResponseFromApiException extends RuntimeException { + + public BadResponseFromApiException() { + } + + public BadResponseFromApiException(String message) { + super(message); + } + +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java new file mode 100644 index 0000000..9ee4d12 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java @@ -0,0 +1,11 @@ +package ru.tinkoff.edu.java.scrapper.exception; + +public class BotClientException extends RuntimeException{ + + public BotClientException() { + } + + public BotClientException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java new file mode 100644 index 0000000..5dd1124 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java @@ -0,0 +1,11 @@ +package ru.tinkoff.edu.java.scrapper.exception; + +public class ChatAlreadyExistException extends RuntimeException { + + public ChatAlreadyExistException() { + } + + public ChatAlreadyExistException(String message) { + super(message); + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java new file mode 100644 index 0000000..29dc8cf --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java @@ -0,0 +1,12 @@ +package ru.tinkoff.edu.java.scrapper.exception; + +public class ChatNotFoundException extends RuntimeException { + + public ChatNotFoundException(String message) { + super(message); + } + + public ChatNotFoundException() { + } + +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java new file mode 100644 index 0000000..9bf30c3 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java @@ -0,0 +1,11 @@ +package ru.tinkoff.edu.java.scrapper.exception; + +public class GitHubRequestException extends RuntimeException{ + + public GitHubRequestException() { + } + + public GitHubRequestException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java new file mode 100644 index 0000000..58a7dfb --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java @@ -0,0 +1,12 @@ +package ru.tinkoff.edu.java.scrapper.exception; + +public class LinkIsAlreadyAddedException extends RuntimeException { + + + public LinkIsAlreadyAddedException(String message) { + super(message); + } + + public LinkIsAlreadyAddedException() { + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java new file mode 100644 index 0000000..e5c5c62 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java @@ -0,0 +1,12 @@ +package ru.tinkoff.edu.java.scrapper.exception; + +public class LinkNotFoundException extends RuntimeException { + + public LinkNotFoundException() { + } + + public LinkNotFoundException(String message) { + super(message); + } + +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java new file mode 100644 index 0000000..e714110 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java @@ -0,0 +1,12 @@ +package ru.tinkoff.edu.java.scrapper.exception; + +public class StackOverflowRequestException extends RuntimeException{ + + public StackOverflowRequestException() { + super(); + } + + public StackOverflowRequestException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java new file mode 100644 index 0000000..72df1e2 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java @@ -0,0 +1,27 @@ +package ru.tinkoff.edu.java.scrapper.mapper; + +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Component; +import ru.tinkoff.edu.java.scrapper.model.Link; +import ru.tinkoff.edu.java.scrapper.model.User; + +import java.sql.ResultSet; +import java.sql.SQLException; + +@Component +public class LinkRowMapper implements RowMapper { + + @Override + public Link mapRow(ResultSet rs, int rowNum) throws SQLException { + Link link = new Link(); + link.setId(rs.getLong("id")); + link.setUrl(rs.getString("url")); + link.setCheckedAt(rs.getTimestamp("checked_at")); + link.setGhPushedAt(rs.getTimestamp("gh_pushed_at")); + link.setGhDescription(rs.getString("gh_description")); + link.setGhForksCount(rs.getInt("gh_forks_count")); + link.setSoAnswerCount(rs.getInt("so_answer_count")); + link.setSoLastEditDate(rs.getTimestamp("so_last_edit_date")); + return link; + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java new file mode 100644 index 0000000..bd76b2b --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java @@ -0,0 +1,20 @@ +package ru.tinkoff.edu.java.scrapper.mapper; + +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Component; +import ru.tinkoff.edu.java.scrapper.model.Relation; +import java.sql.ResultSet; +import java.sql.SQLException; + +@Component +public class SubscriptionRowMapper implements RowMapper { + + @Override + public Relation mapRow(ResultSet rs, int rowNum) throws SQLException { + Relation relation = new Relation(); + relation.setLinkId(rs.getLong("link_id")); + relation.setChatId(rs.getLong("chat_id")); + + return relation; + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java new file mode 100644 index 0000000..4597040 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java @@ -0,0 +1,24 @@ +package ru.tinkoff.edu.java.scrapper.mapper; + +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Component; +import ru.tinkoff.edu.java.scrapper.model.User; + +import java.sql.ResultSet; +import java.sql.SQLException; + + +@Component +public class UserRowMapper implements RowMapper { + + + @Override + public User mapRow(ResultSet rs, int rowNum) throws SQLException { + User user = new User(); + user.setChatId(rs.getLong("chat_id")); + user.setUsername(rs.getString("username")); + user.setFirstName(rs.getString("first_name")); + user.setLastName(rs.getString("last_name")); + return user; + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java new file mode 100644 index 0000000..59b4a92 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java @@ -0,0 +1,31 @@ +package ru.tinkoff.edu.java.scrapper.model.commonDto; + +import lombok.Data; +import java.sql.Timestamp; +import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity; + +@Data +public class Link { + + + private Long id; + private String url; + private Timestamp checkedAt; + private Timestamp ghPushedAt; + private String ghDescription; + private int ghForksCount; + private Timestamp soLastEditDate; + private int soAnswerCount; + public static Link fromEntity(LinkEntity linkEntity){ + Link link = new Link(); + link.setId(linkEntity.getId()); + link.setUrl(linkEntity.getUrl()); + link.setCheckedAt(linkEntity.getCheckedAt()); + link.setGhDescription(linkEntity.getGhDescription()); + link.setGhPushedAt(linkEntity.getGhPushedAt()); + Integer forks = linkEntity.getGhForksCount(); if (forks == null) link.setGhForksCount(0); else link.setGhForksCount(forks); + Integer answers = linkEntity.getSoAnswerCount(); if (answers == null) link.setSoAnswerCount(0); else link.setSoAnswerCount(answers); + link.setSoLastEditDate(linkEntity.getSoLastEditDate()); + return link; + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java new file mode 100644 index 0000000..74f7693 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java @@ -0,0 +1,32 @@ +package ru.tinkoff.edu.java.scrapper.model.commonDto; + +import lombok.Data; +import lombok.NoArgsConstructor; +import ru.tinkoff.edu.java.scrapper.model.jpa.UserEntity; + +@Data +@NoArgsConstructor +public class User { + + public User(Long chatId, String username, String firstName, String lastName) { + this.chatId = chatId; + this.username = username; + this.firstName = firstName; + this.lastName = lastName; + } + + private Long chatId; + private String username; + private String firstName; + private String lastName; + public static UserEntity toEntity(User user){ + UserEntity userEntity = new UserEntity(); + + userEntity.setChatId(user.getChatId()); + userEntity.setUsername(user.getUsername()); + userEntity.setFirstName(user.getFirstName()); + userEntity.setLastName(user.getLastName()); + + return userEntity; + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java new file mode 100644 index 0000000..abe684a --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java @@ -0,0 +1,11 @@ +package ru.tinkoff.edu.java.scrapper.model.jdbcAndJooq; + +import lombok.Data; + +@Data +public class Relation { + + private Long linkId; + private Long chatId; + +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java new file mode 100644 index 0000000..bd4469b --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java @@ -0,0 +1,40 @@ +package ru.tinkoff.edu.java.scrapper.model.jpa; + +import jakarta.persistence.*; +import lombok.Data; +import java.sql.Timestamp; +import java.util.List; + +@Entity +@Table(name = "link") +@Data +public class LinkEntity { + + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "url", unique = true, nullable = false) + private String url; + + @Column(name = "checked_at", nullable = false) + private Timestamp checkedAt; + + @Column(name = "gh_pushed_at") + private Timestamp ghPushedAt; + + @Column(name = "gh_description") + private String ghDescription; + + @Column(name = "gh_forks_count") + private Integer ghForksCount; + + @Column(name = "so_last_edit_date") + private Timestamp soLastEditDate; + + @Column(name = "so_answer_count") + private Integer soAnswerCount; + + +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java new file mode 100644 index 0000000..8f49d40 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java @@ -0,0 +1,30 @@ +package ru.tinkoff.edu.java.scrapper.model.jpa; + +import jakarta.persistence.*; +import lombok.Data; +import java.util.List; + +@Entity +@Table(name = "\"user\"") +@Data +public class UserEntity { + + @Id + @Column(name = "chat_id") + private Long chatId; + + @Column(name = "username", unique = true, nullable = false) + private String username; + + @Column(name = "first_name") + private String firstName; + + @Column(name = "last_name") + private String lastName; + + @ManyToMany(fetch = FetchType.LAZY) + @JoinTable(name = "user_link", + joinColumns = @JoinColumn(name = "chat_id"), + inverseJoinColumns = @JoinColumn(name = "link_id")) + private List links; +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java new file mode 100644 index 0000000..38d0931 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java @@ -0,0 +1,86 @@ +package ru.tinkoff.edu.java.scrapper.repository.jdbc; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; +import ru.tinkoff.edu.java.scrapper.mapper.LinkRowMapper; +import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; +import ru.tinkoff.edu.java.scrapper.repository.LinkRepository; + +import java.sql.Timestamp; +import java.util.List; + +@Slf4j +public class LinkJdbcTemplateRepository implements LinkRepository { + + + private final JdbcTemplate jdbcTemplate; + + private final LinkRowMapper linkRowMapper; + + public LinkJdbcTemplateRepository(JdbcTemplate jdbcTemplate, LinkRowMapper linkRowMapper) { + this.jdbcTemplate = jdbcTemplate; + this.linkRowMapper = linkRowMapper; + } + + + @Override + public List findAll() { + log.info("findAll() method invocation in linkRepo"); + String sql = "select * from link"; + return jdbcTemplate.query(sql, linkRowMapper); + } + + @Override + public Link findByUrl(String url) { + log.info("findByUrl() method invocation in linkRepo"); + String sql = "select * from link where link.url = ?"; + List link = jdbcTemplate.query(sql, linkRowMapper, url); + return link.size() == 0 ? null : link.get(0); + } + + @Override + public void add(Link link) { + log.info("add() method invocation in linkRepo"); + String sql = "insert into link (url, updated_at) values(?, ?)"; + jdbcTemplate.update(sql, link.getUrl(), link.getUpdatedAt()); + } + + + @Override + public void updateDate(Link link) { + log.info("updateDate() method invocation in linkRepo"); + String sql = "update link set updated_at = ? where id = ?"; + jdbcTemplate.update(sql, link.getUpdatedAt(), link.getId()); + } + + @Override + public void remove(Long id) { + log.info("remove() method invocation in linkRepo"); + String sql = "delete from link where link.id = ?"; + jdbcTemplate.update(sql, id); + } + + @Override + //поиск ссылок по критерию + public List findOldLinks(Long timeUpdateDelta) { + log.info("findOldLinks() method invocation in linkRepo"); + Timestamp compareDate = new Timestamp(System.currentTimeMillis() - timeUpdateDelta*1000); + String sql = "select * from link where link.updated_at < ? order by link.updated_at desc"; + return jdbcTemplate.query(sql,linkRowMapper,compareDate); + } + @Override + public void updateGhLink(Link link) { + log.info("updateGhLink() method invocation in linkJdbcRepo"); + String sql = "update link set gh_forks_count = ?, gh_description = ?, gh_pushed_at = ? where id = ?"; + jdbcTemplate.update(sql, link.getGhForksCount(), link.getGhDescription(), link.getGhPushedAt(), link.getId()); + } + + @Override + public void updateSoLink(Link link) { + log.info("updateSoLastEditDate() method invocation in linkJdbcRepo"); + String sql = "update link set so_last_edit_date = ?, so_answer_count = ? where id = ?"; + jdbcTemplate.update(sql, link.getSoLastEditDate(), link.getSoAnswerCount(), link.getId()); + } + +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java new file mode 100644 index 0000000..fce7af7 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java @@ -0,0 +1,75 @@ +package ru.tinkoff.edu.java.scrapper.repository.jdbc; + + +import lombok.extern.slf4j.Slf4j; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; +import ru.tinkoff.edu.java.scrapper.mapper.LinkRowMapper; +import ru.tinkoff.edu.java.scrapper.mapper.SubscriptionRowMapper; +import ru.tinkoff.edu.java.scrapper.model.Link; +import ru.tinkoff.edu.java.scrapper.model.Relation; +import ru.tinkoff.edu.java.scrapper.model.User; +import ru.tinkoff.edu.java.scrapper.repository.SubscriptionRepository; + +import java.util.List; + +@Repository +@Slf4j +public class SubscriptionJdbcTemplateRepository implements SubscriptionRepository { + + private final JdbcTemplate jdbcTemplate; + + private final SubscriptionRowMapper subscriptionRowMapper; + + private final LinkRowMapper linkRowMapper; + + public SubscriptionJdbcTemplateRepository(JdbcTemplate jdbcTemplate, SubscriptionRowMapper subscriptionRowMapper, LinkRowMapper linkRowMapper) { + this.jdbcTemplate = jdbcTemplate; + this.subscriptionRowMapper = subscriptionRowMapper; + this.linkRowMapper = linkRowMapper; + } + + @Override + public List findLinksByChat(Long chatId) { + log.info("findLinksByChat() method invocation in subscriptionRepo"); + String sql = "select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?"; + return jdbcTemplate.query(sql, linkRowMapper, chatId); + } + + @Override + public List findChatsByLink(Long linkId) { + log.info("findChatsByLink() method invocation in subscriptionRepo"); + String sql = "select * from user_link where user_link.link_id = ?"; + return jdbcTemplate.query(sql, subscriptionRowMapper, linkId); + } + + @Override + public Relation findSubscription(Long linkId, Long chatId) { + log.info("findSubscription() method invocation in subscriptionRepo"); + String sql = "select * from user_link rel where rel.chat_id = ? and rel.link_id = ?"; + List relation = jdbcTemplate.query(sql, subscriptionRowMapper, chatId, linkId); + return relation.size() == 0 ? null : relation.get(0); + } + + + @Override + public void addRelation(Relation relation) { + log.info("addRelation() method invocation in subscriptionRepo"); + String sql = "insert into user_link (link_id, chat_id) values(?, ?)"; + jdbcTemplate.update(sql, relation.getLinkId(), relation.getChatId()); + } + + @Override + public void remove(Long linkId, Long chatId) { + log.info("remove() method invocation in subscriptionRepo"); + String sql = "delete from user_link where user_link.link_id = ? and user_link.chat_id = ?"; + jdbcTemplate.update(sql, linkId, chatId); + } + + @Override + public void removeAllByUser(Long chatId) { + log.info("removeAllByUser() method invocation in subscriptionRepo"); + String sql = "delete from user_link where user_link.chat_id = ?"; + jdbcTemplate.update(sql, chatId); + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java new file mode 100644 index 0000000..d59d09c --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java @@ -0,0 +1,59 @@ +package ru.tinkoff.edu.java.scrapper.repository.jdbc; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; +import ru.tinkoff.edu.java.scrapper.mapper.UserRowMapper; +import ru.tinkoff.edu.java.scrapper.model.User; +import ru.tinkoff.edu.java.scrapper.repository.UserRepository; + +import java.util.List; + +@Repository +@Slf4j +public class UserJdbcTemplateRepository implements UserRepository { + + + private final JdbcTemplate jdbcTemplate; + + private final UserRowMapper userRowMapper; + + + public UserJdbcTemplateRepository(JdbcTemplate jdbcTemplate, UserRowMapper userRowMapper) { + this.jdbcTemplate = jdbcTemplate; + this.userRowMapper = userRowMapper; + } + + @Override + public List findAll(){ + log.info("findAll() method invocation in userRepo"); + String sql = "select * from \"user\""; + return jdbcTemplate.query(sql, userRowMapper); + } + + @Override + public User findByChatId(Long id) { + log.info("findByChatId() method invocation in userRepo"); + String sql = "select * from \"user\" where \"user\".chat_id = ?"; + List user = jdbcTemplate.query(sql, userRowMapper, id); + return user.size() == 0 ? null : user.get(0); + } + + @Override + public void add(User user){ + log.info("add() method invocation in userRepo"); + String sql = "insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)"; + jdbcTemplate.update(sql, user.getChatId(), user.getUsername(), user.getFirstName(), user.getLastName()); + } + + @Override + public void remove(Long chatId){ + log.info("remove() method invocation in userRepo"); + String sql = "delete from \"user\" where \"user\".chat_id = ?"; + jdbcTemplate.update(sql,chatId); + } + + + + +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java new file mode 100644 index 0000000..0298278 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java @@ -0,0 +1,21 @@ +package ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract; + +import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; +import java.util.List; + + +public interface LinkRepository { + List findAll(); + + + Link findByUrl(String url); + void add(Link link); + + void updateCheckDate(Link link); + void remove(Long id); + List findOldLinks(Long timeUpdateDeltaInSeconds); + + void updateGhLink(Link link); + + void updateSoLink(Link link); +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java new file mode 100644 index 0000000..0dde7e4 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java @@ -0,0 +1,19 @@ +package ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract; + +import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; +import ru.tinkoff.edu.java.scrapper.model.jdbcAndJooq.Relation; + +import java.util.List; + +public interface SubscriptionRepository { + + List findLinksByChat(Long chatId); + + List findChatsByLink(Long linkId); + + Relation findSubscription(Long linkId, Long chatId); + void addRelation(Relation relation); + void remove(Long linkId, Long chatId); + + void removeAllByUser(Long chatId); +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java new file mode 100644 index 0000000..87cbf34 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java @@ -0,0 +1,13 @@ +package ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract; + +import ru.tinkoff.edu.java.scrapper.model.commonDto.User; +import java.util.List; + +public interface UserRepository { + List findAll(); + + User findByChatId(Long id); + void add(User user); + void remove(Long id); + +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java new file mode 100644 index 0000000..7371ffd --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java @@ -0,0 +1,98 @@ +package ru.tinkoff.edu.java.scrapper.repository.jooq; + +import lombok.extern.slf4j.Slf4j; +import org.jooq.DSLContext; +import org.springframework.stereotype.Repository; +import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; +import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.LinkRepository; +import java.sql.Timestamp; +import java.util.List; +import static ru.tinkoff.edu.java.scrapper.domain.jooq.tables.Link.*; + +@Slf4j +public class LinkJooqRepository implements LinkRepository { + + + private final DSLContext dslContext; + + + + public LinkJooqRepository(DSLContext dslContext) { + this.dslContext = dslContext; + } + + @Override + public List findAll() { + log.info("findAll() method invocation in linkJooqRepo"); + return dslContext.selectFrom(LINK) + .fetchInto(Link.class); + } + + @Override + public Link findByUrl(String url) { + log.info("findByUrl() method invocation in linkJooqRepo"); + return dslContext.selectFrom(LINK) + .where(LINK.URL.eq(url)) + .fetchOneInto(Link.class); + } + + @Override + public void add(Link link) { + log.info("add() method invocation in linkJooqRepo"); + dslContext.insertInto(LINK) + .set(LINK.URL, link.getUrl()) + .set(LINK.CHECKED_AT, link.getCheckedAt().toLocalDateTime()) + .execute(); + } + + @Override + public void updateCheckDate(Link link) { + log.info("updateDate() method invocation in linkJooqRepo"); + dslContext.update(LINK) + .set(LINK.CHECKED_AT, link.getCheckedAt().toLocalDateTime()) + .where(LINK.ID.eq(link.getId())) + .execute(); + } + + @Override + public void remove(Long id) { + log.info("remove() method invocation in linkJooqRepo"); + dslContext.deleteFrom(LINK) + .where(LINK.ID.eq(id)) + .execute(); + } + + @Override + public List findOldLinks(Long timeUpdateDeltaInSeconds) { + log.info("findOldLinks() method invocation in linkJooqRepo"); + Timestamp compareDate = new Timestamp(System.currentTimeMillis() - timeUpdateDeltaInSeconds * 1000); + return dslContext.selectFrom(LINK) + .where(LINK.CHECKED_AT.lessThan(compareDate.toLocalDateTime())) + .orderBy(LINK.CHECKED_AT.desc()) + .fetchInto(Link.class); + } + + @Override + public void updateGhLink(Link link) { + log.info("updateGhLink() method invocation in linkJooqRepo"); + dslContext.update(LINK) + .set(LINK.CHECKED_AT, link.getCheckedAt().toLocalDateTime()) + .set(LINK.GH_FORKS_COUNT, link.getGhForksCount()) + .set(LINK.GH_DESCRIPTION, link.getGhDescription()) + .set(LINK.GH_PUSHED_AT, link.getGhPushedAt().toLocalDateTime()) + .where(LINK.ID.eq(link.getId())) + .execute(); + } + + @Override + public void updateSoLink(Link link) { + log.info("updateSoLink() method invocation in linkJooqRepo"); + dslContext.update(LINK) + .set(LINK.CHECKED_AT, link.getCheckedAt().toLocalDateTime()) + .set(LINK.SO_LAST_EDIT_DATE, link.getSoLastEditDate().toLocalDateTime()) + .set(LINK.SO_ANSWER_COUNT, link.getSoAnswerCount()) + .where(LINK.ID.eq(link.getId())) + .execute(); + } + +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java new file mode 100644 index 0000000..6463de4 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java @@ -0,0 +1,80 @@ +package ru.tinkoff.edu.java.scrapper.repository.jooq; + +import lombok.extern.slf4j.Slf4j; +import org.jooq.DSLContext; +import org.springframework.stereotype.Repository; +import ru.tinkoff.edu.java.scrapper.model.Link; +import ru.tinkoff.edu.java.scrapper.model.Relation; +import ru.tinkoff.edu.java.scrapper.repository.SubscriptionRepository; + +import java.util.List; + +import static ru.tinkoff.edu.java.scrapper.domain.jooq.tables.UserLink.*; +import static ru.tinkoff.edu.java.scrapper.domain.jooq.tables.Link.*; + + +@Repository +@Slf4j +public class SubscriptionJooqRepository implements SubscriptionRepository { + + + private final DSLContext dslContext; + + + public SubscriptionJooqRepository(DSLContext dslContext) { + this.dslContext = dslContext; + } + + + @Override + public List findLinksByChat(Long chatId) { + log.info("findLinksByChat() method invocation in subscriptionJooqRepo"); + return dslContext.select() + .from(LINK) + .join(USER_LINK).on(LINK.ID.eq(USER_LINK.LINK_ID)) + .where(USER_LINK.CHAT_ID.eq(chatId)) + .fetchInto(Link.class); + } + + @Override + public List findChatsByLink(Long linkId) { + log.info("findChatsByLink() method invocation in subscriptionJooqRepo"); + return dslContext.select() + .from(USER_LINK) + .where(USER_LINK.LINK_ID.eq(linkId)) + .fetchInto(Relation.class); + } + + @Override + public Relation findSubscription(Long linkId, Long chatId) { + log.info("findSubscription() method invocation in subscriptionJooqRepo"); + return dslContext.select() + .from(USER_LINK) + .where(USER_LINK.CHAT_ID.eq(chatId).and(USER_LINK.LINK_ID.eq(linkId))) + .fetchOneInto(Relation.class); + } + + @Override + public void addRelation(Relation relation) { + log.info("addRelation() method invocation in subscriptionJooqRepo"); + dslContext.insertInto(USER_LINK, USER_LINK.LINK_ID, USER_LINK.CHAT_ID) + .values(relation.getLinkId(), relation.getChatId()) + .execute(); + } + + @Override + public void remove(Long linkId, Long chatId) { + log.info("remove() method invocation in subscriptionJooqRepo"); + dslContext.deleteFrom(USER_LINK) + .where(USER_LINK.LINK_ID.eq(linkId).and(USER_LINK.CHAT_ID.eq(chatId))) + .execute(); + } + + @Override + public void removeAllByUser(Long chatId) { + log.info("removeAllByUser() method invocation in subscriptionJooqRepo"); + dslContext.deleteFrom(USER_LINK) + .where(USER_LINK.CHAT_ID.eq(chatId)) + .execute(); + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java new file mode 100644 index 0000000..d942314 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java @@ -0,0 +1,59 @@ +package ru.tinkoff.edu.java.scrapper.repository.jooq; + +import lombok.extern.slf4j.Slf4j; +import org.jooq.DSLContext; +import org.springframework.stereotype.Repository; +import ru.tinkoff.edu.java.scrapper.model.commonDto.User; +import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.UserRepository; +import java.util.List; + +import static ru.tinkoff.edu.java.scrapper.domain.jooq.tables.User.*; + +@Repository +@Slf4j +public class UserJooqRepository implements UserRepository { + + private final DSLContext dslContext; + + + public UserJooqRepository(DSLContext dslContext) { + this.dslContext = dslContext; + } + + @Override + public List findAll() { + log.info("findAll() method invocation in userJooqRepo"); + + return dslContext.selectFrom(USER).fetchInto(User.class); + } + + @Override + public User findByChatId(Long id) { + log.info("findByChatId() method invocation in userJooqRepo"); + + return dslContext.selectFrom(USER) + .where(USER.CHAT_ID.eq(id)) + .fetchOneInto(User.class); + } + + @Override + public void add(User user) { + log.info("add() method invocation in userJooqRepo"); + + dslContext.insertInto(USER) + .set(USER.CHAT_ID, user.getChatId()) + .set(USER.USERNAME, user.getUsername()) + .set(USER.FIRST_NAME, user.getFirstName()) + .set(USER.LAST_NAME, user.getLastName()) + .execute(); + } + + @Override + public void remove(Long chatId) { + log.info("remove() method invocation in userJooqRepo"); + + dslContext.deleteFrom(USER) + .where(USER.CHAT_ID.eq(chatId)) + .execute(); + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java new file mode 100644 index 0000000..2f1dab8 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java @@ -0,0 +1,20 @@ +package ru.tinkoff.edu.java.scrapper.repository.jpa; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity; + +import java.sql.Timestamp; +import java.util.List; +import java.util.Optional; + +public interface JpaLinkRepository extends JpaRepository { + Optional findByUrl(String url); + + @Query("select u.chatId from UserEntity u join u.links l where l.id = :id") + List findChatIdsByLinkId(@Param("id") Long id); + + List findByCheckedAtLessThanOrderByCheckedAtDesc(Timestamp compareDate); + +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java new file mode 100644 index 0000000..cdcb762 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java @@ -0,0 +1,22 @@ +package ru.tinkoff.edu.java.scrapper.repository.jpa; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity; +import ru.tinkoff.edu.java.scrapper.model.jpa.UserEntity; + +import java.util.List; +import java.util.Optional; + +public interface JpaUserRepository extends JpaRepository { + + @Query("select link from UserEntity u join u.links link where u.chatId = :chatId") + List findAllLinksByChat(@Param("chatId") Long chatId); + + + @Query("select u from UserEntity u join fetch u.links link where u.chatId = :chatId") + Optional findByChatIdWithLinks(@Param("chatId") Long chatId); + + +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java new file mode 100644 index 0000000..388ebac --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java @@ -0,0 +1,30 @@ +package ru.tinkoff.edu.java.scrapper.rest; + +import org.springframework.web.bind.annotation.*; +import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService; +import ru.tinkoff.edu.java.scrapper.dto.UserAddDto; +import ru.tinkoff.edu.java.scrapper.model.commonDto.User; + +@RestController +@RequestMapping("/tg-chat") +public class ChatRestController { + + + private final TgChatService chatService; + + public ChatRestController(TgChatService chatService) { + this.chatService = chatService; + } + + @PostMapping(value = "{id}") + public void registerChat(@PathVariable Long id, @RequestBody UserAddDto userAddDto) { + chatService.register(new User(id, userAddDto.username(), userAddDto.firstName(), userAddDto.lastName())); + } + + @DeleteMapping(value = "{id}") + public void deleteChat(@PathVariable Long id) { + chatService.unregister(id); + } + + +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java new file mode 100644 index 0000000..5aef3ac --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java @@ -0,0 +1,44 @@ +package ru.tinkoff.edu.java.scrapper.rest; + +import org.springframework.web.bind.annotation.*; +import ru.tinkoff.edu.java.scrapper.dto.AddLinkRequest; +import ru.tinkoff.edu.java.scrapper.dto.LinkResponse; +import ru.tinkoff.edu.java.scrapper.dto.ListLinkResponse; +import ru.tinkoff.edu.java.scrapper.dto.RemoveLinkRequest; +import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; +import ru.tinkoff.edu.java.scrapper.service.contract.LinkService; +import ru.tinkoff.edu.java.scrapper.exception.LinkNotFoundException; +import java.net.URI; +import java.util.List; + +@RestController +@RequestMapping("/links") +public class LinkRestController { + + private final SubscriptionService subscriptionService; + + public LinkRestController(SubscriptionService subscriptionService) { + this.subscriptionService = subscriptionService; + } + + @GetMapping + public ListLinkResponse getLinks(@RequestHeader("Tg-Chat-Id") Long chatId) { + List list = subscriptionService.getLinksByChat(chatId); + return new ListLinkResponse(list, list.size()); + } + + @PostMapping + public LinkResponse addLink(@RequestHeader("Tg-Chat-Id") Long chatId, @RequestBody AddLinkRequest request) { + Link link = subscriptionService.subscribe(chatId, URI.create(request.link())); + return new LinkResponse(link.getId(), link.getUrl()); + } + + @DeleteMapping + public LinkResponse deleteLink(@RequestHeader("Tg-Chat-Id") Long chatId, @RequestBody RemoveLinkRequest request) { + Link link = subscriptionService.unsubscribe(chatId, URI.create(request.link())); + if (link == null) throw new LinkNotFoundException("Ссылка с таким url не отслеживается!"); + return new LinkResponse(link.getId(), link.getUrl()); + } + + +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java new file mode 100644 index 0000000..eec99f7 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java @@ -0,0 +1,26 @@ +package ru.tinkoff.edu.java.scrapper.schedule; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService; + +import java.util.List; + +@Slf4j +@Component +public class LinkUpdateScheduler { + + private final LinkUpdateService linkUpdateService; + + + public LinkUpdateScheduler(LinkUpdateService linkUpdateService, Parser_Link linkParser) { + this.linkUpdateService = linkUpdateService; + } + + @Scheduled(fixedDelayString = "#{@schedulerIntervalMs}") + public void update() { + log.info("update() method invocation in LinkUpdateScheduler"); + linkUpdateService.updateLinks(); + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java new file mode 100644 index 0000000..623f12b --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java @@ -0,0 +1,6 @@ +package ru.tinkoff.edu.java.scrapper.schedule; + +import java.time.Duration; + +public record Scheduler(Duration interval) { +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java new file mode 100644 index 0000000..91471de --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java @@ -0,0 +1,26 @@ +package ru.tinkoff.edu.java.scrapper.service; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.core.AmqpTemplate; +import ru.tinkoff.edu.java.scrapper.configuration.ApplicationConfig; +import ru.tinkoff.edu.java.scrapper.dto.LinkUpdate; + +@Slf4j +//бин регистрируется в конфиге, т.к. его не нужно инициализировать в случае общения по HTTP +public class ScrapperQueueProducer implements UpdateNotificationService { + + private final AmqpTemplate rabbitTemplate; + + private final ApplicationConfig config; + + + public ScrapperQueueProducer(AmqpTemplate rabbitTemplate, ApplicationConfig config) { + this.rabbitTemplate = rabbitTemplate; + this.config = config; + } + + public void updateLink(LinkUpdate update) { + rabbitTemplate.convertAndSend(config.exchangeName(), config.routingKey(), update); + log.info("UpdateMessage " + update + " has been sent"); + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java new file mode 100644 index 0000000..61ee96d --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java @@ -0,0 +1,8 @@ +package ru.tinkoff.edu.java.scrapper.service; + +import ru.tinkoff.edu.java.scrapper.dto.LinkUpdate; + +public interface UpdateNotificationService { + + void updateLink(LinkUpdate request); +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java new file mode 100644 index 0000000..10646d7 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java @@ -0,0 +1,12 @@ +package ru.tinkoff.edu.java.scrapper.service.contract; + +import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; +import java.util.List; + +public interface LinkUpdateService { + + + List getOldLinks(); + + void updateLinks(); +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java new file mode 100644 index 0000000..b35caad --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java @@ -0,0 +1,14 @@ +package ru.tinkoff.edu.java.scrapper.service.contract; + +import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; +import java.net.URI; +import java.util.List; + +public interface SubscriptionService { + + Link add(Long chatId, URI url); + Link remove(Long chatId, URI url); + + List getAllByUser(Long chatId); + +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java new file mode 100644 index 0000000..adf1fde --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java @@ -0,0 +1,11 @@ +package ru.tinkoff.edu.java.scrapper.service.contract; + +import ru.tinkoff.edu.java.scrapper.model.commonDto.User; + +public interface TgChatService { + + void register(User user); + + void unregister(Long chatId); + +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java new file mode 100644 index 0000000..983fdb9 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java @@ -0,0 +1,156 @@ +package ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; +import ru.tinkoff.edu.java.link_parser.parser.Link_Parser; +import ru.tinkoff.edu.java.link_parser.link.GitHub_Link; +import ru.tinkoff.edu.java.link_parser.link.Parser_Link; +import ru.tinkoff.edu.java.link_parser.link.StackOverflow_Link; +import ru.tinkoff.edu.java.scrapper.client.BotClient; +import ru.tinkoff.edu.java.scrapper.client.GitHubClient; +import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient; +import ru.tinkoff.edu.java.scrapper.dto.GitHubResponse; +import ru.tinkoff.edu.java.scrapper.dto.LinkUpdate; +import ru.tinkoff.edu.java.scrapper.dto.StackOverflowItem; +import ru.tinkoff.edu.java.scrapper.exception.GitHubRequestException; +import ru.tinkoff.edu.java.scrapper.exception.StackOverflowRequestException; +//import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; +//import ru.tinkoff.edu.java.scrapper.model.jdbcAndJooq.Relation; +//import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.LinkRepository; +//import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository; +//import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService; + +import java.sql.Timestamp; +import java.time.ZoneOffset; +import java.util.List; + +@Slf4j +public class LinkUpdateServiceImpl implements LinkUpdateService { + + + @Value("${update.delta.time}") + private Long timeUpdateDeltaInSeconds; + + private final LinkRepository linkRepository; + + private final SubscriptionRepository subscriptionRepository; + + private final Link_Parser linkParser; + + private final GitHubClient gitHubClient; + + private final StackOverflowClient stackOverflowClient; + + private final BotClient botClient; + + + public LinkUpdateServiceImpl(LinkRepository linkRepository, SubscriptionRepository subscriptionRepository, Link_Parser linkParser, GitHubClient gitHubClient, StackOverflowClient stackOverflowClient, BotClient botClient) { + this.linkRepository = linkRepository; + this.subscriptionRepository = subscriptionRepository; + this.linkParser = linkParser; + this.gitHubClient = gitHubClient; + this.stackOverflowClient = stackOverflowClient; + this.botClient = botClient; + } + + @Override + public List getOldLinks() { + return linkRepository.findOldLinks(timeUpdateDeltaInSeconds); + } + + + public void updateLinks() { + List oldLinks = getOldLinks(); + + for (Link link : oldLinks) { + Parser_Link result = linkParser.parseUrl(link.getUrl()); + if (result instanceof GitHub_Link) { + try { + boolean isUpdated = false; + String updateDescription = ""; + + + GitHubResponse response = gitHubClient.fetchRepo(((GithubParseResult) result).username(), ((GithubParseResult) result).repository()); + + + if (response.forksCount() != link.getGhForksCount()) { + isUpdated = true; + if (response.forksCount() < link.getGhForksCount()) { + updateDescription += "В репозитории уменьшилось кол-во форков\n"; + } + if (response.forksCount() > link.getGhForksCount()) { + updateDescription += "В репозитории появились новые форки\n"; + } + link.setGhForksCount(response.forksCount()); + } + + + if (link.getGhDescription() == null || !response.description().equals(link.getGhDescription())) { + if (link.getGhDescription() != null) isUpdated = true; + link.setGhDescription(response.description()); + updateDescription += "В репозитории изменилось описание\n"; + } + + if (link.getGhPushedAt() == null || response.pushedAt().toInstant().isAfter(link.getGhPushedAt().toInstant())) { + if (link.getGhPushedAt() != null) isUpdated = true; + link.setGhPushedAt(new Timestamp(response.pushedAt().toInstant().toEpochMilli())); + updateDescription += "В репозитории появился новый commit\n"; + } + + + linkRepository.updateCheckDate(link); + + if (isUpdated) { + Long[] chats = subscriptionRepository.findChatsByLink(link.getId()).stream().map(Relation::getChatId).toArray(Long[]::new); + botClient.updateLink(new LinkUpdate(link.getId(), link.getUrl(), "Вышли обновления в репозитории:\n"+updateDescription, chats)); + } + + + } catch (GitHubRequestException e) { + log.warn(e.getMessage()); + } + + } else if (result instanceof StackOverflow_Link) { + try { + + boolean isUpdated = false; + String updateDescription = ""; + + + StackOverflowItem response = stackOverflowClient.fetchQuestion(((StackOverflowParseResult) result).id()); + + + if (response.lastEditDate() != null && (link.getSoLastEditDate() == null || response.lastEditDate().isAfter(link.getSoLastEditDate().toLocalDateTime().atOffset(ZoneOffset.UTC)))) { + if (link.getSoLastEditDate() != null) isUpdated = true; + link.setSoLastEditDate(new Timestamp(response.lastEditDate().toInstant().toEpochMilli())); + updateDescription += "Текст вопроса был изменён\n"; + } + + if (response.answerCount() != link.getSoAnswerCount()) { + isUpdated = true; + if (response.answerCount() < link.getSoAnswerCount()) { + updateDescription += "На вопрос уменьшилось кол-во ответов\n"; + } + if (response.answerCount() > link.getSoAnswerCount()) { + updateDescription += "На вопрос появились новые ответы\n"; + } + link.setSoAnswerCount(response.answerCount()); + } + + linkRepository.updateCheckDate(link); + + if (isUpdated) { + + Long[] chats = subscriptionRepository.findChatsByLink(link.getId()).stream().map(Relation::getChatId).toArray(Long[]::new); + botClient.updateLink(new LinkUpdate(link.getId(), link.getUrl(), "Вышли обновления в вопросе:\n"+updateDescription, chats)); + } + + } catch (StackOverflowRequestException e) { + log.warn(e.getMessage()); + } + } + } + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java new file mode 100644 index 0000000..4476e8b --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java @@ -0,0 +1,99 @@ +package ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; +import ru.tinkoff.edu.java.scrapper.model.jdbcAndJooq.Relation; +import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.LinkRepository; +import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository; +import ru.tinkoff.edu.java.scrapper.service.contract.SubscriptionService; + +import java.net.URI; +import java.sql.Timestamp; +import java.util.List; + + +@Slf4j +public class SubscriptionServiceImpl implements SubscriptionService { + + + private final LinkRepository linkRepository; + + private final SubscriptionRepository subscriptionRepository; + + + + public SubscriptionServiceImpl(LinkRepository linkRepository, SubscriptionRepository subscriptionRepository) { + this.linkRepository = linkRepository; + this.subscriptionRepository = subscriptionRepository; + } + + @Override + @Transactional + public Link subscribe(Long chatId, URI url) { + log.info("subscribe() method invocation in SubscriptionServiceImpl. chatId = "+chatId+" url = "+url.toString()); + Link link = linkRepository.findByUrl(url.toString()); + if (link == null) { + link = new Link(); + link.setUrl(url.toString()); + link.setCheckedAt(new Timestamp(System.currentTimeMillis())); + linkRepository.add(link); + //обращение ниже нужно, чтобы получить id из БД + link = linkRepository.findByUrl(link.getUrl()); + } + Relation relation = subscriptionRepository.findSubscription(link.getId(), chatId); + + if (relation == null) { + relation = new Relation(); + relation.setChatId(chatId); + relation.setLinkId(link.getId()); + subscriptionRepository.addRelation(relation); + } + return link; + } + + @Override + @Transactional + public Link unsubscribe(Long chatId, URI url) { + log.info("unsubscribe() method invocation in SubscriptionServiceImpl. chatId = "+chatId+" url = "+url.toString()); + Link link = linkRepository.findByUrl(url.toString()); + + if (link != null) { +// linkRepository.remove(link.getId()); + subscriptionRepository.remove(link.getId(), chatId); + } + return link; + } + + @Override + public List getLinksByChat(Long chatId) { + log.info("getLinksByChat() method invocation in SubscriptionServiceImpl. chatId = "+chatId); + return subscriptionRepository.findLinksByChat(chatId); + } + + @Override + public List getChatIdsByLink(Long linkId) { + log.info("getChatIdsByLink() method invocation in SubscriptionServiceImpl. linkId = "+linkId); + return null; + } + + @Override + public Link add(Long chatId, URI url) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Link remove(Long chatId, URI url) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List getAllByUser(Long chatId) { + // TODO Auto-generated method stub + return null; + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java new file mode 100644 index 0000000..84a130a --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java @@ -0,0 +1,42 @@ +package ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import ru.tinkoff.edu.java.scrapper.exception.ChatAlreadyExistException; +import ru.tinkoff.edu.java.scrapper.model.commonDto.User; +import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository; +import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.UserRepository; +import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService; + +@Slf4j +public class TgChatServiceImpl implements TgChatService { + + private final UserRepository userRepository; + + private final SubscriptionRepository subscriptionRepository; + + + public TgChatServiceImpl(UserRepository userRepository, SubscriptionRepository subscriptionRepository) { + this.userRepository = userRepository; + this.subscriptionRepository = subscriptionRepository; + } + + @Override + public void register(User user) { + log.info("register() method invocation in TgChatServiceImpl. chatId = "+user.getChatId()); + User userInBd = userRepository.findByChatId(user.getChatId()); + if (userInBd != null) throw new ChatAlreadyExistException(); + userRepository.add(user); + } + + @Override + @Transactional + public void unregister(Long chatId) { + log.info("unregister() method invocation in TgChatServiceImpl. chatId = "+chatId); + userRepository.remove(chatId); + subscriptionRepository.removeAllByUser(chatId); + } + +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java new file mode 100644 index 0000000..f27d081 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java @@ -0,0 +1,174 @@ +package ru.tinkoff.edu.java.scrapper.service.jpa.impl; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import ru.tinkoff.edu.java.link_parser.parser.Link_Parser; +import ru.tinkoff.edu.java.link_parser.link.GitHub_Link; +import ru.tinkoff.edu.java.link_parser.link.Parser_Link; +import ru.tinkoff.edu.java.link_parser.link.StackOverflow_Link; +import ru.tinkoff.edu.java.scrapper.client.BotClient; +import ru.tinkoff.edu.java.scrapper.client.GitHubClient; +import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient; +import ru.tinkoff.edu.java.scrapper.dto.GitHubResponse; +import ru.tinkoff.edu.java.scrapper.dto.LinkUpdate; +import ru.tinkoff.edu.java.scrapper.dto.StackOverflowItem; +import ru.tinkoff.edu.java.scrapper.exception.GitHubRequestException; +import ru.tinkoff.edu.java.scrapper.exception.StackOverflowRequestException; +import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; +import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity; +import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaLinkRepository; +import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService; + +import java.sql.Timestamp; +import java.time.ZoneOffset; +import java.util.List; + +@Slf4j +public class JpaLinkUpdateServiceImpl implements LinkUpdateService { + + @Value("${update.delta.time}") + private Long timeUpdateDeltaInSeconds; + + private final JpaLinkRepository linkRepository; + + + + private final Link_Parser linkParser; + + private final GitHubClient gitHubClient; + + private final StackOverflowClient stackOverflowClient; + + private final BotClient botClient; + + + public JpaLinkUpdateServiceImpl(JpaLinkRepository linkRepository, LinkParser linkParser, GitHubClient gitHubClient, StackOverflowClient stackOverflowClient, BotClient botClient) { + this.linkRepository = linkRepository; + this.linkParser = linkParser; + this.gitHubClient = gitHubClient; + this.stackOverflowClient = stackOverflowClient; + this.botClient = botClient; + } + + @Override + public List getOldLinks() { + log.info("getOldLinks() method invocation in JpaLinkUpdateServiceImpl"); + Timestamp compareDate = new Timestamp(System.currentTimeMillis() - timeUpdateDeltaInSeconds*1000); + return linkRepository.findByCheckedAtLessThanOrderByCheckedAtDesc(compareDate).stream().map(Link::fromEntity).toList(); + } + + + public List getOldEntityLinks() { + Timestamp compareDate = new Timestamp(System.currentTimeMillis() - timeUpdateDeltaInSeconds*1000); + return linkRepository.findByCheckedAtLessThanOrderByCheckedAtDesc(compareDate); + } + + @Override + @Transactional + public void updateLinks() { + log.info("updateLinks() method invocation in JpaLinkUpdateServiceImpl"); + List oldLinks = getOldEntityLinks(); + + for (LinkEntity link : oldLinks) { + Parser_Link result = linkParser.parseUrl(link.getUrl()); + if (result instanceof GitHub_Link) { + try { + boolean isUpdated = false; + String updateDescription = ""; + + + System.out.println(link.getUrl()); + GitHubResponse response = gitHubClient.fetchRepo(((GitHub_Link) result).username(), ((GithubParseResult) result).repository()); + System.out.println(response); + + + if (link.getGhForksCount() == null || response.forksCount() != link.getGhForksCount()) { + isUpdated = true; + if (link.getGhForksCount() == null) {link.setGhForksCount(0); isUpdated = false;} + if (isUpdated && response.forksCount() < link.getGhForksCount()) { + updateDescription += "В репозитории уменьшилось кол-во форков\n"; + } + if (isUpdated && response.forksCount() > link.getGhForksCount()) { + updateDescription += "В репозитории появились новые форки\n"; + } + link.setGhForksCount(response.forksCount()); + } + + + if (link.getGhDescription() == null || !response.description().equals(link.getGhDescription())) { + if (link.getGhDescription() != null) isUpdated = true; + link.setGhDescription(response.description()); + updateDescription += "В репозитории изменилось описание\n"; + } + + if (link.getGhPushedAt() == null || response.pushedAt().toInstant().isAfter(link.getGhPushedAt().toInstant())) { + if (link.getGhPushedAt() != null) isUpdated = true; + link.setGhPushedAt(new Timestamp(response.pushedAt().toInstant().toEpochMilli())); + updateDescription += "В репозитории появился новый commit\n"; + } + + link.setCheckedAt(new Timestamp(System.currentTimeMillis())); + + linkRepository.save(link); + + if (isUpdated) { + List chatsIds = linkRepository.findChatIdsByLinkId(link.getId()); + botClient.updateLink(new LinkUpdate(link.getId(), link.getUrl(), "Вышли обновления в репозитории:\n"+updateDescription, chatsIds.toArray(new Long[0]))); + } + + + } catch (GitHubRequestException e) { + log.warn(e.getMessage()); + } + + } else if (result instanceof StackOverflow_Link) { + try { + + boolean isUpdated = false; + String updateDescription = ""; + + + System.out.println(link.getUrl()); + StackOverflowItem response = stackOverflowClient.fetchQuestion(((StackOverflowParseResult) result).id()); + System.out.println(response); + + + + if (response.lastEditDate() != null && (link.getSoLastEditDate() == null || response.lastEditDate().isAfter(link.getSoLastEditDate().toLocalDateTime().atOffset(ZoneOffset.UTC)))) { + if (link.getSoLastEditDate() != null) isUpdated = true; + link.setSoLastEditDate(new Timestamp(response.lastEditDate().toInstant().toEpochMilli())); + updateDescription += "Текст вопроса был изменён\n"; + } + + if (link.getSoAnswerCount() == null || response.answerCount() != link.getSoAnswerCount()) { + isUpdated = true; + if (link.getSoAnswerCount() == null) {link.setSoAnswerCount(0); isUpdated = false;} + if (isUpdated && response.answerCount() < link.getSoAnswerCount()) { + updateDescription += "На вопрос уменьшилось кол-во ответов\n"; + } + if (isUpdated && response.answerCount() > link.getSoAnswerCount()) { + updateDescription += "На вопрос появились новые ответы\n"; + } + link.setSoAnswerCount(response.answerCount()); + } + + + link.setCheckedAt(new Timestamp(System.currentTimeMillis())); + + linkRepository.save(link); + + if (isUpdated) { + List chatsIds = linkRepository.findChatIdsByLinkId(link.getId()); + botClient.updateLink(new LinkUpdate(link.getId(), link.getUrl(), "Вышли обновления в вопросе:\n"+updateDescription, chatsIds.toArray(new Long[0]))); + } + + } catch (StackOverflowRequestException e) { + log.warn(e.getMessage()); + } + } + } + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java new file mode 100644 index 0000000..c5c9749 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java @@ -0,0 +1,100 @@ +package ru.tinkoff.edu.java.scrapper.service.jpa.impl; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import ru.tinkoff.edu.java.scrapper.exception.ChatNotFoundException; +import ru.tinkoff.edu.java.scrapper.exception.LinkNotFoundException; +import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; +import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity; +import ru.tinkoff.edu.java.scrapper.model.jpa.UserEntity; +import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaLinkRepository; +import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaUserRepository; +import ru.tinkoff.edu.java.scrapper.service.contract.SubscriptionService; + +import java.net.URI; +import java.sql.Timestamp; +import java.util.List; +import java.util.Optional; + +@Slf4j +public class JpaSubscriptionServiceImpl implements SubscriptionService { + + private final JpaLinkRepository linkRepository; + + private final JpaUserRepository userRepository; + + public JpaSubscriptionServiceImpl(JpaLinkRepository linkRepository, JpaUserRepository userRepository) { + this.linkRepository = linkRepository; + this.userRepository = userRepository; + } + + + @Override + @Transactional + public Link subscribe(Long chatId, URI url) { + log.info("subscribe() method invocation in JpaSubscriptionServiceImpl. chatId = "+chatId+" url = "+url.toString()); + Optional optionalLink = linkRepository.findByUrl(url.toString()); + LinkEntity linkToAdd = new LinkEntity(); + if (optionalLink.isEmpty()) { + linkToAdd.setUrl(url.toString()); + } else { + linkToAdd = optionalLink.get(); + } + linkToAdd.setCheckedAt(new Timestamp(System.currentTimeMillis())); + linkRepository.save(linkToAdd); + + Optional optionalUser = userRepository.findById(chatId); + if (optionalUser.isEmpty()) throw new ChatNotFoundException("Такой чат не зарегистрирован!"); + UserEntity user = optionalUser.get(); + List userLinks = user.getLinks(); + + if (!userLinks.contains(linkToAdd)) { + userLinks.add(linkToAdd); + } + + userRepository.save(user); + return Link.fromEntity(linkToAdd); + } + + @Override + @Transactional + public Link unsubscribe(Long chatId, URI url) { + log.info("unsubscribe() method invocation in JpaSubscriptionServiceImpl. chatId = "+chatId+" url = "+url.toString()); + Optional optionalUser = userRepository.findByChatIdWithLinks(chatId); + Optional optionalLink = linkRepository.findByUrl(url.toString()); + + + if (optionalUser.isEmpty()) throw new ChatNotFoundException("Такой пользователь не зарегистрирован"); + + UserEntity user = optionalUser.get(); + + List userLinks = user.getLinks(); + + if (optionalLink.isEmpty() || !userLinks.contains(optionalLink.get())) + throw new LinkNotFoundException("Такая ссылка не отслеживается"); + + userLinks.remove(optionalLink.get()); + userRepository.save(user); + + return Link.fromEntity(optionalLink.get()); + } + + @Override + public List getLinksByChat(Long chatId) { + log.info("getAllByUser() method invocation in JpaSubscriptionServiceImpl. chatId = "+chatId); + Optional optionalUser = userRepository.findById(chatId); + if (optionalUser.isEmpty()) throw new ChatNotFoundException("Такой чат не зарегистрирован!"); + return userRepository.findAllLinksByChat(chatId).stream().map(Link::fromEntity).toList(); + } + + + @Override + public List getChatIdsByLink(Long linkId) { + log.info("getChatIdsByLink() method invocation in JpaSubscriptionServiceImpl. linkId = "+linkId); + Optional optionalLink = linkRepository.findById(linkId); + if (optionalLink.isEmpty()) throw new LinkNotFoundException("Такая ссылка не отслеживается"); + return linkRepository.findChatIdsByLinkId(linkId); + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java new file mode 100644 index 0000000..b87e274 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java @@ -0,0 +1,43 @@ +package ru.tinkoff.edu.java.scrapper.service.jpa.impl; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; +import ru.tinkoff.edu.java.scrapper.exception.ChatAlreadyExistException; +import ru.tinkoff.edu.java.scrapper.exception.ChatNotFoundException; +import ru.tinkoff.edu.java.scrapper.model.commonDto.User; +import ru.tinkoff.edu.java.scrapper.model.jpa.UserEntity; +import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaUserRepository; +import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService; + +import java.util.Optional; + + +@Slf4j +public class JpaTgChatServiceImpl implements TgChatService { + + private final JpaUserRepository userRepository; + + public JpaTgChatServiceImpl(JpaUserRepository userRepository) { + this.userRepository = userRepository; + } + + @Override + public void register(User user) { + log.info("register() method invocation in JpaTgChatServiceImpl. User chatId = "+user.getChatId()); + Optional optionalUser = userRepository.findById(user.getChatId()); + if (optionalUser.isPresent()) throw new ChatAlreadyExistException("Такой чат уже зарегистрирован!"); + userRepository.save(User.toEntity(user)); + } + + @Override + public void unregister(Long chatId) { + log.info("unregister() method invocation in JpaTgChatServiceImpl. User chatId = "+chatId); + Optional optionalUser = userRepository.findById(chatId); + if (optionalUser.isEmpty()) throw new ChatNotFoundException("Такой чат не зарегистрирован!"); + userRepository.delete(optionalUser.get()); + } + + + +} \ No newline at end of file diff --git a/FP/scrapper/src/main/resources/application.properties b/FP/scrapper/src/main/resources/application.properties new file mode 100644 index 0000000..3761f00 --- /dev/null +++ b/FP/scrapper/src/main/resources/application.properties @@ -0,0 +1,23 @@ +server.port=8080 +app.test=beamer-scrapper +gh.baseurl=https://api.github.com +so.baseurl=https://api.stackexchange.com/2.3/ +bot.baseurl=http://localhost:8081 +app.scheduler.interval=61000 +update.delta.time=20 +springdoc.swagger-ui.path=/swagger-ui + +spring.datasource.driver-class-name=org.postgresql.Driver +spring.datasource.url=jdbc:postgresql://localhost:5432/scrapper +spring.datasource.username=romanova +spring.datasource.password=12345654321 +spring.jpa.properties.hibernate.show_sql=true + +spring.rabbitmq.host=localhost +spring.rabbitmq.port=5672 +spring.rabbitmq.username=romanova +spring.rabbitmq.password=12345654321 +app.queue-name=scrapper-bot-queue +app.exchange-name=scrapper-bot-exchange +app.routing-key=scrapper-bot-key +app.use-queue=true diff --git a/FP/scrapper/src/main/resources/logback-test.xml b/FP/scrapper/src/main/resources/logback-test.xml new file mode 100644 index 0000000..900637e --- /dev/null +++ b/FP/scrapper/src/main/resources/logback-test.xml @@ -0,0 +1,17 @@ + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n + + + + + + + + + + + + +. diff --git a/FP/scrapper/src/test/java/scrapper/DatabaseTest.java b/FP/scrapper/src/test/java/scrapper/DatabaseTest.java new file mode 100644 index 0000000..1c2378c --- /dev/null +++ b/FP/scrapper/src/test/java/scrapper/DatabaseTest.java @@ -0,0 +1,38 @@ +package scrapper; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.sql.*; + +public class DatabaseTest extends IntegrationEnvironment{ + + + @Test + @DisplayName("Тест для проверки запуска контейнера с PostgreSQL") + public void testIfContainerIsRunning() { + Assertions.assertTrue(POSTGRES_CONTAINER.isRunning(),"Ошибка запуска контейнера PostgreSQL"); + } + + @Test + @DisplayName("Тест для проверки успешного применения миграций") + void testMigrations() throws SQLException { + try (Connection conn = DriverManager.getConnection(IntegrationEnvironment.POSTGRES_CONTAINER.getJdbcUrl(), + IntegrationEnvironment.POSTGRES_CONTAINER.getUsername(), + IntegrationEnvironment.POSTGRES_CONTAINER.getPassword()); + Statement statement = conn.createStatement()) { + + ResultSet resultSetUser = statement.executeQuery("SELECT * FROM \"user\""); + Assertions.assertFalse(resultSetUser.next(), "Таблица user не создана"); + ResultSet resultSetLink = statement.executeQuery("SELECT * FROM \"link\""); + Assertions.assertFalse(resultSetLink.next(), "Таблица link не создана"); + ResultSet resultSetUserLink = statement.executeQuery("SELECT * FROM \"user_link\""); + Assertions.assertFalse(resultSetUserLink.next(),"Таблица user_link не создана"); + } + } + + + + +} \ No newline at end of file diff --git a/FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java b/FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java new file mode 100644 index 0000000..2f0bdfa --- /dev/null +++ b/FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java @@ -0,0 +1,54 @@ +package scrapper; + +import liquibase.Contexts; +import liquibase.LabelExpression; +import liquibase.Liquibase; +import liquibase.database.Database; +import liquibase.database.DatabaseFactory; +import liquibase.database.jvm.JdbcConnection; +import liquibase.exception.LiquibaseException; +import liquibase.resource.DirectoryResourceAccessor; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Testcontainers; + +import java.io.File; +import java.io.FileNotFoundException; +import java.nio.file.Path; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +abstract class IntegrationEnvironment { + + static final String IMAGE_VERSION = "postgres:15"; + + static final PostgreSQLContainer POSTGRES_CONTAINER; + + static { + POSTGRES_CONTAINER = new PostgreSQLContainer(IMAGE_VERSION) + .withDatabaseName("scrapper") + .withUsername("lwbeamer") + .withPassword("2281337"); + + + POSTGRES_CONTAINER.start(); + executeMigrations(); + } + + private static void executeMigrations() { + try (Connection conn = DriverManager.getConnection(IntegrationEnvironment.POSTGRES_CONTAINER.getJdbcUrl(), IntegrationEnvironment.POSTGRES_CONTAINER.getUsername(), + IntegrationEnvironment.POSTGRES_CONTAINER.getPassword())) { + Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(conn)); + Path changeLogFile = new File("").toPath().toAbsolutePath().getParent().resolve("migrations"); + Liquibase liquibase = new Liquibase("master.xml",new DirectoryResourceAccessor(changeLogFile), database); + liquibase.update(new Contexts(), new LabelExpression()); + } catch (SQLException | LiquibaseException e) { + throw new RuntimeException("Failed to execute migrations", e); + } catch (FileNotFoundException e) { + throw new RuntimeException("Changelog file not found",e); + } + } + + public static void stopContainer() { + POSTGRES_CONTAINER.stop(); + } diff --git a/FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java b/FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java new file mode 100644 index 0000000..d0ac18a --- /dev/null +++ b/FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java @@ -0,0 +1,38 @@ +package scrapper.environment; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.sql.*; + +public class DatabaseTest extends IntegrationEnvironment{ + + + @Test + @DisplayName("Тест для проверки запуска контейнера с PostgreSQL") + public void testIfContainerIsRunning() { + Assertions.assertTrue(POSTGRES_CONTAINER.isRunning(),"Ошибка запуска контейнера PostgreSQL"); + } + + @Test + @DisplayName("Тест для проверки успешного применения миграций") + void testMigrations() throws SQLException { + try (Connection conn = DriverManager.getConnection(IntegrationEnvironment.POSTGRES_CONTAINER.getJdbcUrl(), + IntegrationEnvironment.POSTGRES_CONTAINER.getUsername(), + IntegrationEnvironment.POSTGRES_CONTAINER.getPassword()); + Statement statement = conn.createStatement()) { + + ResultSet resultSetUser = statement.executeQuery("SELECT * FROM \"user\""); + Assertions.assertFalse(resultSetUser.next(), "Таблица user не создана"); + ResultSet resultSetLink = statement.executeQuery("SELECT * FROM \"link\""); + Assertions.assertFalse(resultSetLink.next(), "Таблица link не создана"); + ResultSet resultSetUserLink = statement.executeQuery("SELECT * FROM \"user_link\""); + Assertions.assertFalse(resultSetUserLink.next(),"Таблица user_link не создана"); + } + } + + + + +} \ No newline at end of file diff --git a/FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java b/FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java new file mode 100644 index 0000000..416b086 --- /dev/null +++ b/FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java @@ -0,0 +1,81 @@ +package scrapper.environment; + +import liquibase.Contexts; +import liquibase.LabelExpression; +import liquibase.Liquibase; +import liquibase.database.Database; +import liquibase.database.DatabaseFactory; +import liquibase.database.jvm.JdbcConnection; +import liquibase.exception.LiquibaseException; +import liquibase.resource.DirectoryResourceAccessor; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.ContextConfiguration; +import org.testcontainers.containers.PostgreSQLContainer; + +import javax.sql.DataSource; +import java.io.File; +import java.io.FileNotFoundException; +import java.nio.file.Path; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +@ContextConfiguration(classes = IntegrationEnvironment.EnvironmentConfiguration.class) +public abstract class IntegrationEnvironment { + + + @Configuration + static class EnvironmentConfiguration{ + @Bean + public DataSource dataSource() { + return DataSourceBuilder.create() + .url(POSTGRES_CONTAINER.getJdbcUrl()) + .username(POSTGRES_CONTAINER.getUsername()) + .password(POSTGRES_CONTAINER.getPassword()) + .build(); + } + + @Bean + public JdbcTemplate jdbcTemplate(DataSource dataSource){ + return new JdbcTemplate(dataSource); + } + + } + + static final String IMAGE_VERSION = "postgres:15"; + + static final PostgreSQLContainer POSTGRES_CONTAINER; + + static { + POSTGRES_CONTAINER = new PostgreSQLContainer(IMAGE_VERSION) + .withDatabaseName("scrapper") + .withUsername("lwbeamer") + .withPassword("2281337"); + + + POSTGRES_CONTAINER.start(); + executeMigrations(); + } + + private static void executeMigrations() { + try (Connection conn = DriverManager.getConnection(IntegrationEnvironment.POSTGRES_CONTAINER.getJdbcUrl(), IntegrationEnvironment.POSTGRES_CONTAINER.getUsername(), + IntegrationEnvironment.POSTGRES_CONTAINER.getPassword())) { + Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(conn)); + Path changeLogFile = new File("").toPath().toAbsolutePath().getParent().resolve("migrations"); + Liquibase liquibase = new Liquibase("master.xml",new DirectoryResourceAccessor(changeLogFile), database); + liquibase.update(new Contexts(), new LabelExpression()); + } catch (SQLException | LiquibaseException e) { + throw new RuntimeException("Failed to execute migrations", e); + } catch (FileNotFoundException e) { + throw new RuntimeException("Changelog file not found",e); + } + } + + public static void stopContainer() { + POSTGRES_CONTAINER.stop(); + } + +} \ No newline at end of file diff --git a/FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java b/FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java new file mode 100644 index 0000000..a4ff395 --- /dev/null +++ b/FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java @@ -0,0 +1,8 @@ +package scrapper.environment; + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration; + +@EnableAutoConfiguration(exclude = { LiquibaseAutoConfiguration.class }) +public class TestConfiguration { +} \ No newline at end of file diff --git a/FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java b/FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java new file mode 100644 index 0000000..436f01a --- /dev/null +++ b/FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java @@ -0,0 +1,151 @@ +package scrapper.jdbc; + +import scrapper.environment.IntegrationEnvironment; +import scrapper.environment.TestConfiguration; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.annotation.Rollback; +import org.springframework.transaction.annotation.Transactional; +import ru.tinkoff.edu.java.scrapper.ScrapperApplication; +import ru.tinkoff.edu.java.scrapper.mapper.LinkRowMapper; +import ru.tinkoff.edu.java.scrapper.model.Link; +import ru.tinkoff.edu.java.scrapper.repository.*; +import ru.tinkoff.edu.java.scrapper.repository.jdbc.LinkJdbcTemplateRepository; + +import java.sql.Timestamp; +import java.util.List; + +@SpringBootTest(classes = {ScrapperApplication.class, TestConfiguration.class}) +public class JdbcLinkTest extends IntegrationEnvironment { + + @Autowired + private LinkJdbcTemplateRepository linkRepository; + + @Autowired + private LinkRowMapper linkRowMapper; + + @Autowired + private JdbcTemplate jdbcTemplate; + + + @Test + @Transactional + @Rollback + public void addLinkTest() { + List beforeAddLink = jdbcTemplate.query("select * from link where link.url='https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file'", linkRowMapper); + + Link linkToAdd = new Link(); + linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file"); + linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis())); + linkRepository.add(linkToAdd); + + List addedLink = jdbcTemplate.query("select * from link where link.url='https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file'", linkRowMapper); + + Assertions.assertEquals(beforeAddLink.size(), 0); + Assertions.assertNotNull(addedLink.get(0)); + Assertions.assertEquals("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file", addedLink.get(0).getUrl()); + } + + + @Test + @Transactional + @Rollback + public void removeLinkTest() { + List beforeAddLink = jdbcTemplate.query("select * from link where link.url='https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file'", linkRowMapper); + + Link linkToAdd = new Link(); + linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file"); + linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis())); + jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt()); + + List afterInsertionLink = jdbcTemplate.query("select * from link where link.url='https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file'", linkRowMapper); + + linkRepository.remove(afterInsertionLink.get(0).getId()); + + List afterRemovingLink = jdbcTemplate.query("select * from link where link.url='https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file'", linkRowMapper); + + + Assertions.assertEquals(beforeAddLink.size(), 0); + Assertions.assertEquals(afterInsertionLink.size(), 1); + Assertions.assertEquals(afterRemovingLink.size(), 0); + } + + + @Test + @Transactional + @Rollback + public void findAllTest() { + List beforeAddLink = jdbcTemplate.query("select * from link", linkRowMapper); + + for (int i = 0; i < 10; i++) { + Link linkToAdd = new Link(); + linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i); + linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis())); + jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt()); + } + + List afterInsertionLink = linkRepository.findAll(); + + Assertions.assertEquals(beforeAddLink.size(), 0); + Assertions.assertEquals(afterInsertionLink.size(), 10); + } + + + @Test + @Transactional + @Rollback + public void findByUrlTest(){ + List beforeAddLink = jdbcTemplate.query("select * from link", linkRowMapper); + + for (int i = 0; i < 10; i++) { + Link linkToAdd = new Link(); + linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i); + linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis())); + jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt()); + } + + List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper); + Link foundedByUrlLink = linkRepository.findByUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file0"); + + Assertions.assertEquals(beforeAddLink.size(), 0); + Assertions.assertEquals(afterInsertionLink.size(), 10); + Assertions.assertNotNull(foundedByUrlLink); + } + + + @Test + @Transactional + @Rollback + public void updateDateTest(){ + List beforeAddLink = jdbcTemplate.query("select * from link", linkRowMapper); + + + Link linkToAdd = new Link(); + linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file"); + Timestamp timestampBefore = new Timestamp(System.currentTimeMillis()); + linkToAdd.setUpdatedAt(timestampBefore); + jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt()); + + + List linkBeforeUpdate = jdbcTemplate.query("select * from link where link.url = ?", linkRowMapper, "https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file"); + + Assertions.assertEquals(linkBeforeUpdate.get(0).getUpdatedAt(),timestampBefore); + + linkBeforeUpdate.get(0).setUpdatedAt(new Timestamp(100000)); + + linkRepository.updateDate(linkBeforeUpdate.get(0)); + + List linkAfterUpdate = jdbcTemplate.query("select * from link where link.url = ?", linkRowMapper, "https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file"); + + Assertions.assertEquals(beforeAddLink.size(), 0); + Assertions.assertEquals(linkAfterUpdate.get(0).getUpdatedAt(),new Timestamp(100000)); + } + + + + + +} \ No newline at end of file diff --git a/FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java b/FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java new file mode 100644 index 0000000..0813c59 --- /dev/null +++ b/FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java @@ -0,0 +1,251 @@ +package scrapper.jdbc; + +import scrapper.environment.IntegrationEnvironment; +import scrapper.environment.TestConfiguration; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.annotation.Rollback; +import org.springframework.transaction.annotation.Transactional; +import ru.tinkoff.edu.java.scrapper.ScrapperApplication; +import ru.tinkoff.edu.java.scrapper.mapper.LinkRowMapper; +import ru.tinkoff.edu.java.scrapper.mapper.SubscriptionRowMapper; +import ru.tinkoff.edu.java.scrapper.model.Link; +import ru.tinkoff.edu.java.scrapper.model.Relation; +import ru.tinkoff.edu.java.scrapper.model.User; +import ru.tinkoff.edu.java.scrapper.repository.jdbc.LinkJdbcTemplateRepository; +import ru.tinkoff.edu.java.scrapper.repository.jdbc.SubscriptionJdbcTemplateRepository; + +import java.sql.Timestamp; +import java.util.List; + +@SpringBootTest(classes = {ScrapperApplication.class, TestConfiguration.class}) +public class JdbcSubscriptionTest extends IntegrationEnvironment { + + @Autowired + private SubscriptionJdbcTemplateRepository subscriptionRepository; + + @Autowired + private LinkRowMapper linkRowMapper; + + @Autowired + private SubscriptionRowMapper subscriptionRowMapper; + + @Autowired + private JdbcTemplate jdbcTemplate; + + + @Test + @Transactional + @Rollback + public void findLinksByChatTest() { + List beforeAddLink = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L); + + jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 42L, "robtop21", "Robert", "Polson"); + jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 50L, "alucard", "Will", "Smith"); + + //всего добавим 20 ссылок + for (int i = 0; i < 20; i++) { + Link linkToAdd = new Link(); + linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i); + linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis())); + jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt()); + } + + List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper); + + //из 20-ти ссылок подпишемся лишь на 10 + for (int i = 0; i < 10; i++) { + jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(i).getId(), 42L); + } + + //на оставшиеся 10 подпишем другого пользователя + for (int i = 10; i < 20; i++) { + jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(i).getId(), 50L); + } + + List userLinks = subscriptionRepository.findLinksByChat(42L); + + Assertions.assertEquals(beforeAddLink.size(), 0); + Assertions.assertEquals(afterInsertionLink.size(), 20); + Assertions.assertEquals(userLinks.size(), 10); + } + + @Test + @Transactional + @Rollback + public void removeRelationTest() { + List beforeAddLink = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L); + + jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 42L, "robtop21", "Robert", "Polson"); + + for (int i = 0; i < 20; i++) { + Link linkToAdd = new Link(); + linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i); + linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis())); + jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt()); + } + + List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper); + + for (int i = 0; i < 10; i++) { + jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(i).getId(), 42L); + } + + List userLinksBeforeRemove = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L); + + subscriptionRepository.remove(afterInsertionLink.get(0).getId(), 42L); + subscriptionRepository.remove(afterInsertionLink.get(4).getId(), 42L); + subscriptionRepository.remove(afterInsertionLink.get(6).getId(), 42L); + + List userLinksAfterRemove = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L); + + Assertions.assertEquals(beforeAddLink.size(), 0); + Assertions.assertEquals(afterInsertionLink.size(), 20); + Assertions.assertEquals(userLinksBeforeRemove.size(), 10); + Assertions.assertEquals(userLinksAfterRemove.size(), 7); + } + + + @Test + @Transactional + @Rollback + public void addRelationTest() { + List beforeAddLink = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L); + + jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 42L, "robtop21", "Robert", "Polson"); + + for (int i = 0; i < 20; i++) { + Link linkToAdd = new Link(); + linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i); + linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis())); + jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt()); + } + + List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper); + + for (int i = 0; i < 10; i++) { + Relation relation = new Relation(); + relation.setLinkId(afterInsertionLink.get(i).getId()); + relation.setChatId(42L); + subscriptionRepository.addRelation(relation); + } + + + List userLinks = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L); + + Assertions.assertEquals(beforeAddLink.size(), 0); + Assertions.assertEquals(afterInsertionLink.size(), 20); + Assertions.assertEquals(userLinks.size(), 10); + } + + + @Test + @Transactional + @Rollback + public void findChatsByLinkTest() { + List beforeAddRelation = jdbcTemplate.query("select * from user_link", subscriptionRowMapper); + + + for (int i = 0; i < 10; i++) { + User user = new User(42L + i, "robtop21" + i, "Robert", "Polson"); + + jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", + user.getChatId(), + user.getUsername(), + user.getFirstName(), + user.getLastName()); + } + + + Link linkToAdd = new Link(); + linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file"); + linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis())); + jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt()); + + List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper); + + + for (int i = 0; i < 7; i++) { + Relation relation = new Relation(); + relation.setLinkId(afterInsertionLink.get(0).getId()); + relation.setChatId(42L + i); + subscriptionRepository.addRelation(relation); + } + + List afterSubscribe = subscriptionRepository.findChatsByLink(afterInsertionLink.get(0).getId()); + + Assertions.assertEquals(beforeAddRelation.size(), 0); + Assertions.assertEquals(afterSubscribe.size(), 7); + } + + @Test + @Transactional + @Rollback + public void findSubscriptionTest() { + List beforeAddRelation = jdbcTemplate.query("select * from user_link", subscriptionRowMapper); + + jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 42L, "robtop21", "Robert", "Polson"); + + + Link linkToAdd = new Link(); + linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file"); + linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis())); + jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt()); + List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper); + jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(0).getId(), 42L); + + Relation relation = subscriptionRepository.findSubscription(afterInsertionLink.get(0).getId(), 42L); + + + Assertions.assertEquals(beforeAddRelation.size(),0); + Assertions.assertEquals(afterInsertionLink.size(),1); + Assertions.assertNotNull(relation); + } + + + @Test + @Transactional + @Rollback + public void removeAllByUserTest(){ + List beforeAddRelation = jdbcTemplate.query("select * from user_link", subscriptionRowMapper); + + + jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 42L, "robtop21", "Robert", "Polson"); + jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 50L, "alucard", "Will", "Smith"); + + //всего добавим 20 ссылок + for (int i = 0; i < 20; i++) { + Link linkToAdd = new Link(); + linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i); + linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis())); + jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt()); + } + + List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper); + + //из 20-ти ссылок подпишемся лишь на 10 + for (int i = 0; i < 10; i++) { + jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(i).getId(), 42L); + } + + //на оставшиеся 10 подпишем другого пользователя + for (int i = 10; i < 20; i++) { + jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(i).getId(), 50L); + } + + List userLinksBeforeDelete = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L); + + subscriptionRepository.removeAllByUser(42L); + + List userLinksAfterDelete = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L); + + Assertions.assertEquals(beforeAddRelation.size(),0); + Assertions.assertEquals(afterInsertionLink.size(), 20); + Assertions.assertEquals(userLinksBeforeDelete.size(), 10); + Assertions.assertEquals(userLinksAfterDelete.size(), 0); + } + +} diff --git a/FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java b/FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java new file mode 100644 index 0000000..df7d245 --- /dev/null +++ b/FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java @@ -0,0 +1,135 @@ +package scrapper.jdbc; + +import scrapper.environment.IntegrationEnvironment; +import scrapper.environment.TestConfiguration; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.annotation.Rollback; +import org.springframework.transaction.annotation.Transactional; +import ru.tinkoff.edu.java.scrapper.ScrapperApplication; +import ru.tinkoff.edu.java.scrapper.mapper.UserRowMapper; +import ru.tinkoff.edu.java.scrapper.model.User; +import ru.tinkoff.edu.java.scrapper.repository.jdbc.UserJdbcTemplateRepository; + +import java.util.List; + +@SpringBootTest(classes = {ScrapperApplication.class, TestConfiguration.class}) +public class JdbcUserTest extends IntegrationEnvironment { + + @Autowired + private UserJdbcTemplateRepository userRepository; + + @Autowired + private UserRowMapper userRowMapper; + + @Autowired + private JdbcTemplate jdbcTemplate; + + + @Test + @Transactional + @Rollback + public void addUserTest() { + List beforeAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper); + + User user = new User(42L, "robtop21", "Robert","Polson"); + + + userRepository.add(user); + + List afterAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper); + + Assertions.assertEquals(beforeAddUser.size(), 0); + Assertions.assertEquals(afterAddUser.size(), 1); + Assertions.assertNotNull(afterAddUser.get(0)); + Assertions.assertEquals(afterAddUser.get(0).getChatId(), 42L); + } + + + @Test + @Transactional + @Rollback + public void removeUserTest() { + List beforeAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper); + + User user = new User(42L, "robtop21", "Robert","Polson"); + + + + jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", + user.getChatId(), + user.getUsername(), + user.getFirstName(), + user.getLastName()); + + + List afterAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper); + + userRepository.remove(42L); + + List afterRemoveUser = jdbcTemplate.query("select * from \"user\"", userRowMapper); + + + Assertions.assertEquals(beforeAddUser.size(), 0); + Assertions.assertEquals(afterAddUser.size(), 1); + Assertions.assertNotNull(afterAddUser.get(0)); + Assertions.assertEquals(afterAddUser.get(0).getChatId(), 42L); + Assertions.assertEquals(afterRemoveUser.size(), 0); + } + + @Test + @Transactional + @Rollback + public void findAllTest() { + List beforeAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper); + + + for (int i = 0; i < 10; i++) { + User user = new User(42L + i, "robtop21" + i, "Robert","Polson"); + + jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", + user.getChatId(), + user.getUsername(), + user.getFirstName(), + user.getLastName()); + } + + List afterInsertionUser = userRepository.findAll(); + + Assertions.assertEquals(beforeAddUser.size(), 0); + Assertions.assertEquals(afterInsertionUser.size(), 10); + } + + + @Test + @Transactional + @Rollback + public void findByChatIdTest(){ + List beforeAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper); + + + for (int i = 0; i < 10; i++) { + User user = new User(42L + i, "robtop21" + i, "Robert","Polson"); + + jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", + user.getChatId(), + user.getUsername(), + user.getFirstName(), + user.getLastName()); + } + + List afterInsertionUser = jdbcTemplate.query("select * from \"user\"", userRowMapper); + + User foundedByIdUser = userRepository.findByChatId(42L); + + Assertions.assertEquals(beforeAddUser.size(), 0); + Assertions.assertEquals(afterInsertionUser.size(), 10); + Assertions.assertNotNull(foundedByIdUser); + + } + + +} \ No newline at end of file From 616dc051d07b08fa47ae1f7fcd1a679557ad97d6 Mon Sep 17 00:00:00 2001 From: Ray <113240139+Ray-Not@users.noreply.github.com> Date: Mon, 15 May 2023 12:26:38 +0300 Subject: [PATCH 3/9] Rew --- FP/.project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FP/.project b/FP/.project index 89d138f..7b5c63d 100644 --- a/FP/.project +++ b/FP/.project @@ -1,6 +1,6 @@ - project + FP From 686e734b1e204252d352ba8ad1ab4e022a7366bc Mon Sep 17 00:00:00 2001 From: Ray-Not <2sinsincuba@gmail.com> Date: Fri, 19 May 2023 03:02:02 +0500 Subject: [PATCH 4/9] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=BD=D0=BE=D1=81?= =?UTF-8?q?=20=D1=81=20hw5=20=D1=80=D0=B5=D0=BF=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 7 +- FP/.project | 18 -- FP/bot/.classpath | 34 --- FP/bot/.dbeaver/.credentials-config.json.bak | Bin 112 -> 0 bytes FP/bot/.dbeaver/.data-sources.json.bak | 4 - FP/bot/.dbeaver/.project-metadata.json.bak | 1 - FP/bot/.dbeaver/data-sources.json | 6 - FP/bot/.dbeaver/project-metadata.json | 1 - FP/bot/.dbeaver/project-settings.json | 1 - FP/bot/.gitignore | 1 - FP/bot/.project | 24 -- .../org.eclipse.core.resources.prefs | 6 - FP/bot/.settings/org.eclipse.jdt.core.prefs | 9 - FP/bot/.settings/org.eclipse.m2e.core.prefs | 4 - FP/bot/pom.xml | 109 ++++---- .../tinkoff/edu/java/bot/BotApplication.java | 17 +- .../java/bot/advice/AppExceptionHandler.java | 23 -- .../edu/java/bot/api/BotController.java | 14 + .../exceptionHandler/BotExceptionHandler.java | 36 +++ .../java/bot/api/model/ApiErrorResponse.java | 11 + .../edu/java/bot/api/model/LinkUpdate.java | 6 + .../edu/java/bot/client/ScrapperClient.java | 97 ------- .../bot/client/ScrapperClientException.java | 11 - .../edu/java/bot/commands/Command.java | 20 -- .../edu/java/bot/commands/CommandsEnum.java | 33 --- .../edu/java/bot/commands/HelpCommand.java | 23 -- .../edu/java/bot/commands/ListCommand.java | 48 ---- .../edu/java/bot/commands/StartCommand.java | 55 ---- .../edu/java/bot/commands/TrackCommand.java | 47 ---- .../edu/java/bot/commands/UntrackCommand.java | 49 ---- .../bot/configuration/ApplicationConfig.java | 14 +- .../bot/configuration/BotConfiguration.java | 66 ----- .../configuration/ClientConfiguration.java | 27 -- .../LinkParserConfiguration.java | 14 - .../configuration/RabbitMQConfiguration.java | 8 +- .../bot/configuration/configRecords/Bot.java | 4 + .../configRecords/Scheduler.java | 5 + .../edu/java/bot/dto/AddLinkRequest.java | 6 - .../edu/java/bot/dto/ApiErrorResponse.java | 7 - .../tinkoff/edu/java/bot/dto/BotCommand.java | 8 - .../ru/tinkoff/edu/java/bot/dto/Link.java | 10 - .../edu/java/bot/dto/LinkResponse.java | 11 - .../tinkoff/edu/java/bot/dto/LinkUpdate.java | 5 - .../edu/java/bot/dto/ListLinkResponse.java | 6 - .../edu/java/bot/dto/RemoveLinkRequest.java | 5 - .../edu/java/bot/dto/SetCommandRequest.java | 7 - .../tinkoff/edu/java/bot/dto/UserAddDto.java | 8 - .../bot/exceptions/ChatNotFoundException.java | 10 - .../LinkIsNotRegisteredToChatException.java | 10 - .../edu/java/bot/firstBot/BotMain.java | 36 +++ .../ru/tinkoff/edu/java/bot/firstBot/DB.java | 42 +++ .../edu/java/bot/firstBot/MessageHandler.java | 30 +++ .../edu/java/bot/firstBot/Updater.java | 39 +++ .../edu/java/bot/firstBot/commands/All.java | 7 + .../edu/java/bot/firstBot/commands/Help.java | 11 + .../edu/java/bot/firstBot/commands/List.java | 10 + .../edu/java/bot/firstBot/commands/Start.java | 9 + .../edu/java/bot/firstBot/commands/Track.java | 13 + .../java/bot/firstBot/commands/Untrack.java | 14 + .../edu/java/bot/rest/BotRestController.java | 30 --- .../bot/schedule/LinkUpdaterScheduler.java | 17 ++ .../edu/java/bot/service/UpdateService.java | 8 - .../java/bot/service/UpdateServiceImpl.java | 26 -- .../ru/tinkoff/edu/java/bot/telegram/Bot.java | 53 ---- .../bot/telegram/UserMessageProcessor.java | 67 ----- .../edu/java/bot/telegram/UserState.java | 5 - .../src/main/resources/application.properties | 17 +- FP/bot/src/main/resources/botapi.yml | 59 ++++ FP/bot/src/test/java/BotTest.java | 24 ++ FP/bot/src/test/java/bot/BotTest.java | 123 --------- FP/docker-compose.yml | 68 +++-- FP/link-parser/.classpath | 41 --- FP/link-parser/.gitignore | 1 - FP/link-parser/.project | 23 -- .../org.eclipse.core.resources.prefs | 6 - .../.settings/org.eclipse.jdt.core.prefs | 9 - .../.settings/org.eclipse.m2e.core.prefs | 4 - FP/link-parser/pom.xml | 46 ++-- .../java/link_parser/link/GitHub_Link.java | 5 - .../java/link_parser/link/Parser_Link.java | 5 - .../link_parser/link/StackOverflow_Link.java | 5 - .../edu/java/link_parser/parser/Abstract.java | 27 -- .../edu/java/link_parser/parser/Github.java | 31 --- .../java/link_parser/parser/Link_Parser.java | 16 -- .../link_parser/parser/StackOverflow.java | 34 --- .../edu/java/linkparser/LinkParser.java | 18 ++ .../linkparser/absracts/AbstractParser.java | 20 ++ .../java/linkparser/absracts/GitParser.java | 20 ++ .../java/linkparser/absracts/OtherParser.java | 9 + .../java/linkparser/absracts/StackParser.java | 19 ++ .../src/test/java/LinkParserTest.java | 103 +------ FP/migrations/01-schema-1.sql | 11 - FP/migrations/02-schema-2.sql | 15 -- FP/migrations/03-schema-3.sql | 10 - FP/migrations/create.sql | 18 -- FP/migrations/delete.sql | 3 - FP/migrations/insert.sql | 37 --- FP/migrations/master.xml | 13 - FP/pom.xml | 151 +++++------ FP/scrapper-jooq/.classpath | 28 -- FP/scrapper-jooq/.gitignore | 1 - FP/scrapper-jooq/.project | 23 -- .../org.eclipse.core.resources.prefs | 4 - .../.settings/org.eclipse.jdt.core.prefs | 9 - .../.settings/org.eclipse.m2e.core.prefs | 4 - FP/scrapper-jooq/pom.xml | 40 --- .../src/main/java/JooqCodegen.java | 49 ---- FP/scrapper/.classpath | 41 --- FP/scrapper/.gitignore | 1 - FP/scrapper/.project | 23 -- .../org.eclipse.core.resources.prefs | 6 - .../.settings/org.eclipse.jdt.core.prefs | 9 - .../.settings/org.eclipse.m2e.core.prefs | 4 - FP/scrapper/pom.xml | 92 +++---- .../java/scrapper/ScrapperApplication.java | 19 +- .../scrapper/advice/AppExceptionHandler.java | 33 --- .../scrapper/api/ScrapperControllerLinks.java | 44 +++ .../scrapper/api/ScrapperControllerTg.java | 29 ++ .../scrapper/api/model/AddLinkRequest.java | 3 + .../java/scrapper/api/model/ChatResponse.java | 3 + .../scrapper/api/model/LinkChatResponse.java | 3 + .../java/scrapper/api/model/LinkResponse.java | 3 + .../scrapper/api/model/ListLinksResponse.java | 6 + .../scrapper/api/model/RemoveLinkRequest.java | 3 + .../scrapper/api/model/UpdateService.java | 4 + .../edu/java/scrapper/client/BotClient.java | 38 --- .../scrapper/client/ClientConfiguration.java | 57 ++++ .../java/scrapper/client/GitHubClient.java | 47 ---- .../java/scrapper/client/GitHubRecord.java | 19 ++ .../scrapper/client/StackOverflowClient.java | 44 --- .../scrapper/client/StackOverflowRecord.java | 10 + .../java/scrapper/client/WeatherRecord.java | 11 + .../configuration/ApplicationConfig.java | 23 +- .../configuration/ClientConfiguration.java | 44 --- .../configuration/HTTPConfiguration.java | 28 -- .../LinkParserConfiguration.java | 14 - .../configuration/RabbitMQConfiguration.java | 17 +- .../acess/JdbcAccessConfiguration.java | 99 ------- .../acess/JooqAccessConfiguration.java | 84 ------ .../acess/JpaAccessConfiguration.java | 61 ----- .../edu/java/scrapper/dto/AddLinkRequest.java | 5 - .../java/scrapper/dto/ApiErrorResponse.java | 6 - .../edu/java/scrapper/dto/GitHubResponse.java | 25 -- .../edu/java/scrapper/dto/LinkResponse.java | 5 - .../edu/java/scrapper/dto/LinkUpdate.java | 5 - .../java/scrapper/dto/ListLinkResponse.java | 8 - .../java/scrapper/dto/RemoveLinkRequest.java | 5 - .../java/scrapper/dto/StackOverflowItem.java | 8 - .../scrapper/dto/StackOverflowResponse.java | 8 - .../edu/java/scrapper/dto/UserAddDto.java | 8 - .../BadResponseFromApiException.java | 12 - .../exception/BotClientException.java | 11 - .../exception/ChatAlreadyExistException.java | 11 - .../exception/ChatNotFoundException.java | 12 - .../exception/GitHubRequestException.java | 11 - .../LinkIsAlreadyAddedException.java | 12 - .../exception/LinkNotFoundException.java | 12 - .../StackOverflowRequestException.java | 12 - .../exceptions/ScrapperExceptionHandler.java | 78 ++++++ .../EntryExsistException.java | 12 + .../EntryNotExsistException.java | 12 + .../customExceptions/NullDBException.java | 12 + .../customExceptions/NullLinkException.java | 12 + .../UnauthorizationException.java | 12 + .../exceptions/model/ApiErrorResponse.java | 7 + .../java/scrapper/jdbc/JdbcChatService.java | 26 ++ .../java/scrapper/jdbc/JdbcLinkService.java | 75 ++++++ .../java/scrapper/jdbc/config/jdbcBean.java | 25 ++ .../scrapper/jdbc/mappers/ChatMapper.java | 14 + .../scrapper/jdbc/mappers/LinkChatMapper.java | 14 + .../scrapper/jdbc/mappers/LinkMapper.java | 15 ++ .../jdbc/operations/ChatOperations.java | 50 ++++ .../jdbc/operations/LinkChatOperations.java | 61 +++++ .../jdbc/operations/LinkOperations.java | 83 ++++++ .../java/scrapper/mapper/LinkRowMapper.java | 27 -- .../mapper/SubscriptionRowMapper.java | 20 -- .../java/scrapper/mapper/UserRowMapper.java | 24 -- .../java/scrapper/model/commonDto/Link.java | 31 --- .../java/scrapper/model/commonDto/User.java | 32 --- .../scrapper/model/jdbcAndJooq/Relation.java | 11 - .../java/scrapper/model/jpa/LinkEntity.java | 40 --- .../java/scrapper/model/jpa/UserEntity.java | 30 --- .../rabbitmq}/ScrapperQueueListener.java | 4 +- .../ScrapperQueueProducer.java | 19 +- .../jdbc/LinkJdbcTemplateRepository.java | 86 ------ .../SubscriptionJdbcTemplateRepository.java | 75 ------ .../jdbc/UserJdbcTemplateRepository.java | 59 ---- .../jdbcAndJooqContract/LinkRepository.java | 21 -- .../SubscriptionRepository.java | 19 -- .../jdbcAndJooqContract/UserRepository.java | 13 - .../repository/jooq/LinkJooqRepository.java | 98 ------- .../jooq/SubscriptionJooqRepository.java | 80 ------ .../repository/jooq/UserJooqRepository.java | 59 ---- .../repository/jpa/JpaLinkRepository.java | 20 -- .../repository/jpa/JpaUserRepository.java | 22 -- .../scrapper/rest/ChatRestController.java | 30 --- .../scrapper/rest/LinkRestController.java | 44 --- .../schedule/LinkUpdateScheduler.java | 26 -- .../schedule/LinkUpdaterScheduler.java | 63 +++++ .../edu/java/scrapper/schedule/Scheduler.java | 3 +- .../service/UpdateNotificationService.java | 8 - .../service/contract/LinkUpdateService.java | 12 - .../service/contract/SubscriptionService.java | 14 - .../service/contract/TgChatService.java | 11 - .../impl/LinkUpdateServiceImpl.java | 156 ----------- .../impl/SubscriptionServiceImpl.java | 99 ------- .../jdbcAndJooq/impl/TgChatServiceImpl.java | 42 --- .../jpa/impl/JpaLinkUpdateServiceImpl.java | 174 ------------ .../jpa/impl/JpaSubscriptionServiceImpl.java | 100 ------- .../jpa/impl/JpaTgChatServiceImpl.java | 43 --- .../src/main/resources/application.properties | 26 +- .../src/main/resources/logback-test.xml | 17 -- .../src/main/resources/scrapperapi.yml | 184 +++++++++++++ FP/scrapper/src/test/java/BaseTest.java | 11 + .../src/test/java/IntegrationEnvironment.java | 45 ++++ FP/scrapper/src/test/java/JdbcAddTest.java | 9 + .../src/test/java/scrapper/DatabaseTest.java | 38 --- .../java/scrapper/IntegrationEnvironment.java | 54 ---- .../scrapper/environment/DatabaseTest.java | 38 --- .../environment/IntegrationEnvironment.java | 81 ------ .../environment/TestConfiguration.java | 8 - .../test/java/scrapper/jdbc/JdbcLinkTest.java | 151 ----------- .../scrapper/jdbc/JdbcSubscriptionTest.java | 251 ------------------ .../test/java/scrapper/jdbc/JdbcUserTest.java | 135 ---------- README.md | 1 - 225 files changed, 1790 insertions(+), 4992 deletions(-) delete mode 100644 FP/.project delete mode 100644 FP/bot/.classpath delete mode 100644 FP/bot/.dbeaver/.credentials-config.json.bak delete mode 100644 FP/bot/.dbeaver/.data-sources.json.bak delete mode 100644 FP/bot/.dbeaver/.project-metadata.json.bak delete mode 100644 FP/bot/.dbeaver/data-sources.json delete mode 100644 FP/bot/.dbeaver/project-metadata.json delete mode 100644 FP/bot/.dbeaver/project-settings.json delete mode 100644 FP/bot/.gitignore delete mode 100644 FP/bot/.project delete mode 100644 FP/bot/.settings/org.eclipse.core.resources.prefs delete mode 100644 FP/bot/.settings/org.eclipse.jdt.core.prefs delete mode 100644 FP/bot/.settings/org.eclipse.m2e.core.prefs delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/BotController.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/exceptionHandler/BotExceptionHandler.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/ApiErrorResponse.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/LinkUpdate.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Bot.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Scheduler.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/BotMain.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/DB.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/MessageHandler.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/Updater.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/All.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Help.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/List.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Start.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Track.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Untrack.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/schedule/LinkUpdaterScheduler.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java create mode 100644 FP/bot/src/main/resources/botapi.yml create mode 100644 FP/bot/src/test/java/BotTest.java delete mode 100644 FP/bot/src/test/java/bot/BotTest.java delete mode 100644 FP/link-parser/.classpath delete mode 100644 FP/link-parser/.gitignore delete mode 100644 FP/link-parser/.project delete mode 100644 FP/link-parser/.settings/org.eclipse.core.resources.prefs delete mode 100644 FP/link-parser/.settings/org.eclipse.jdt.core.prefs delete mode 100644 FP/link-parser/.settings/org.eclipse.m2e.core.prefs delete mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/GitHub_Link.java delete mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/Parser_Link.java delete mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/StackOverflow_Link.java delete mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java delete mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java delete mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Link_Parser.java delete mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/LinkParser.java create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/AbstractParser.java create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/GitParser.java create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/OtherParser.java create mode 100644 FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/StackParser.java delete mode 100644 FP/migrations/01-schema-1.sql delete mode 100644 FP/migrations/02-schema-2.sql delete mode 100644 FP/migrations/03-schema-3.sql delete mode 100644 FP/migrations/create.sql delete mode 100644 FP/migrations/delete.sql delete mode 100644 FP/migrations/insert.sql delete mode 100644 FP/migrations/master.xml delete mode 100644 FP/scrapper-jooq/.classpath delete mode 100644 FP/scrapper-jooq/.gitignore delete mode 100644 FP/scrapper-jooq/.project delete mode 100644 FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs delete mode 100644 FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs delete mode 100644 FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs delete mode 100644 FP/scrapper-jooq/pom.xml delete mode 100644 FP/scrapper-jooq/src/main/java/JooqCodegen.java delete mode 100644 FP/scrapper/.classpath delete mode 100644 FP/scrapper/.gitignore delete mode 100644 FP/scrapper/.project delete mode 100644 FP/scrapper/.settings/org.eclipse.core.resources.prefs delete mode 100644 FP/scrapper/.settings/org.eclipse.jdt.core.prefs delete mode 100644 FP/scrapper/.settings/org.eclipse.m2e.core.prefs delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerLinks.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerTg.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/AddLinkRequest.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ChatResponse.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkChatResponse.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkResponse.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ListLinksResponse.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/RemoveLinkRequest.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/UpdateService.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/ClientConfiguration.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubRecord.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowRecord.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/WeatherRecord.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/ScrapperExceptionHandler.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/EntryExsistException.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/EntryNotExsistException.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/NullDBException.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/NullLinkException.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/UnauthorizationException.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/model/ApiErrorResponse.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcChatService.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/config/jdbcBean.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/ChatMapper.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkChatMapper.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkMapper.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/ChatOperations.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkChatOperations.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java rename FP/{bot/src/main/java/ru/tinkoff/edu/java/bot/service => scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq}/ScrapperQueueListener.java (95%) rename FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/{service => rabbitmq}/ScrapperQueueProducer.java (50%) delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdaterScheduler.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java delete mode 100644 FP/scrapper/src/main/resources/logback-test.xml create mode 100644 FP/scrapper/src/main/resources/scrapperapi.yml create mode 100644 FP/scrapper/src/test/java/BaseTest.java create mode 100644 FP/scrapper/src/test/java/IntegrationEnvironment.java create mode 100644 FP/scrapper/src/test/java/JdbcAddTest.java delete mode 100644 FP/scrapper/src/test/java/scrapper/DatabaseTest.java delete mode 100644 FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java delete mode 100644 FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java delete mode 100644 FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java delete mode 100644 FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java delete mode 100644 FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java delete mode 100644 FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java delete mode 100644 FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java diff --git a/.gitignore b/.gitignore index 862eb15..d457c3c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Compiled class file *.class + # Log file *.log @@ -23,4 +24,8 @@ hs_err_pid* # idea -.idea \ No newline at end of file +FP/.idea/ + +# volumes +FP/migrations/ +FP/rabbitmq/ \ No newline at end of file diff --git a/FP/.project b/FP/.project deleted file mode 100644 index 7b5c63d..0000000 --- a/FP/.project +++ /dev/null @@ -1,18 +0,0 @@ - - - FP - - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.m2e.core.maven2Nature - org.jkiss.dbeaver.DBeaverNature - - diff --git a/FP/bot/.classpath b/FP/bot/.classpath deleted file mode 100644 index 0b9fa8d..0000000 --- a/FP/bot/.classpath +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/FP/bot/.dbeaver/.credentials-config.json.bak b/FP/bot/.dbeaver/.credentials-config.json.bak deleted file mode 100644 index 8320c631e208c3ad7467cf2d9db83d85e90f14f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 112 zcmV-$0FVC>%bw`qlvu4i=Wrho)ja=8tm(6RtT%VUiv(RbXd+9@8O^=>KI816Agz S3>36s#U(-2xgbD9^um4; - - bot - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.jkiss.dbeaver.DBeaverNature - - diff --git a/FP/bot/.settings/org.eclipse.core.resources.prefs b/FP/bot/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index 29abf99..0000000 --- a/FP/bot/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,6 +0,0 @@ -eclipse.preferences.version=1 -encoding//src/main/java=UTF-8 -encoding//src/main/resources=UTF-8 -encoding//src/test/java=UTF-8 -encoding//src/test/resources=UTF-8 -encoding/=UTF-8 diff --git a/FP/bot/.settings/org.eclipse.jdt.core.prefs b/FP/bot/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 5e4ec05..0000000 --- a/FP/bot/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,9 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.methodParameters=generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 -org.eclipse.jdt.core.compiler.compliance=17 -org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore -org.eclipse.jdt.core.compiler.release=enabled -org.eclipse.jdt.core.compiler.source=17 diff --git a/FP/bot/.settings/org.eclipse.m2e.core.prefs b/FP/bot/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f..0000000 --- a/FP/bot/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/FP/bot/pom.xml b/FP/bot/pom.xml index 11dc02c..60f49bd 100644 --- a/FP/bot/pom.xml +++ b/FP/bot/pom.xml @@ -1,23 +1,50 @@ - - 4.0.0 - - project - project - 0.0.1-SNAPSHOT - - bot - + + + + org.example + FP + 1.0 + + + 4.0.0 + + bot + + + 3.0.1 + 2.7.6 + + + + - org.springframework.boot - spring-boot-starter-web + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.0.2 + + + org.apache.commons + commons-lang3 + 3.10 + org.springframework.boot spring-boot-starter-validation + ${starter-validation.version} - + org.springframework.boot - spring-boot-starter-webflux + spring-boot-starter-web + ${starter-web.version} + + + org.apache.logging.log4j + log4j-to-slf4j + + org.springframework.boot @@ -40,64 +67,22 @@ lombok true - - org.springdoc - springdoc-openapi-starter-webmvc-ui - 2.0.2 - + com.github.pengrad java-telegram-bot-api 6.6.0 - - ru.tinkoff.edu - link-parser - 1.0-SNAPSHOT - - - org.springframework - spring-context - 6.0.3 - - - org.springframework - spring-test - 6.0.6 - test - + org.junit.jupiter - junit-jupiter-params - - - org.mockito - mockito-core + junit-jupiter + test - org.springframework.boot - spring-boot-starter-amqp + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 - - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-failsafe-plugin - - - org.apache.maven.plugins - maven-surefire-plugin - - - \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java index 50cd2b8..312857e 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java @@ -4,13 +4,18 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; import ru.tinkoff.edu.java.bot.configuration.ApplicationConfig; +import ru.tinkoff.edu.java.bot.firstBot.BotMain; + @SpringBootApplication @EnableConfigurationProperties(ApplicationConfig.class) -public class BotApplication { - public static void main(String[] args) { - var ctx = SpringApplication.run(BotApplication.class, args); - ApplicationConfig config = ctx.getBean(ApplicationConfig.class); +public class BotApplication +{ + public static void main(String[] args){ + var ctx = SpringApplication.run(BotApplication.class, args); + ApplicationConfig config = ctx.getBean(ApplicationConfig.class); - } -} \ No newline at end of file + BotMain bot = new BotMain(config.bot().token()); + bot.start(); + } +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java deleted file mode 100644 index 12c0975..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/advice/AppExceptionHandler.java +++ /dev/null @@ -1,23 +0,0 @@ -package ru.tinkoff.edu.java.bot.advice; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestControllerAdvice; -import ru.tinkoff.edu.java.bot.dto.ApiErrorResponse; -import ru.tinkoff.edu.java.bot.exceptions.ChatNotFoundException; -import ru.tinkoff.edu.java.bot.exceptions.LinkIsNotRegisteredToChatException; - -import java.util.Arrays; - -@RestControllerAdvice -public class AppExceptionHandler { - - @ExceptionHandler({LinkIsNotRegisteredToChatException.class, ChatNotFoundException.class}) - @ResponseStatus(value = HttpStatus.BAD_REQUEST) - public ApiErrorResponse handleNotFoundExceptions(RuntimeException exception) { - return new ApiErrorResponse( - "Error", HttpStatus.BAD_REQUEST.toString(), exception.getClass().getName(), exception.getMessage(), Arrays.stream(exception.getStackTrace()).map(StackTraceElement::toString).toList().toArray(String[]::new)); - } - -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/BotController.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/BotController.java new file mode 100644 index 0000000..25186cf --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/BotController.java @@ -0,0 +1,14 @@ +package ru.tinkoff.edu.java.bot.api; + +import org.springframework.web.bind.annotation.*; +import ru.tinkoff.edu.java.bot.api.model.LinkUpdate; + +@RestController +@RequestMapping("/update") +public class BotController { + + @PostMapping + public String updateChat(@RequestBody LinkUpdate update) { + return update.toString(); + } +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/exceptionHandler/BotExceptionHandler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/exceptionHandler/BotExceptionHandler.java new file mode 100644 index 0000000..732a56e --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/exceptionHandler/BotExceptionHandler.java @@ -0,0 +1,36 @@ +package ru.tinkoff.edu.java.bot.api.exceptionHandler; + +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import ru.tinkoff.edu.java.bot.api.model.ApiErrorResponse; + +@RestControllerAdvice +public class BotExceptionHandler { + + private String getDescription(String message) { + ApiErrorResponse errorObj = new ApiErrorResponse( + message, + null, + null, + null, + null + ); + return errorObj.description(); + } + + @ExceptionHandler(HttpMessageNotReadableException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public String MessageNotReadable(HttpMessageNotReadableException Exception) { + return getDescription("Некорректные значения параметров или их нет!"); + } + + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public String MethodNotSupported(HttpRequestMethodNotSupportedException Exception) { + return getDescription("Метод не разрешен!"); + } +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/ApiErrorResponse.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/ApiErrorResponse.java new file mode 100644 index 0000000..f43001e --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/ApiErrorResponse.java @@ -0,0 +1,11 @@ +package ru.tinkoff.edu.java.bot.api.model; + +import java.util.List; + +public record ApiErrorResponse( + String description, + String code, + String exceptionName, + String exceptionMessage, + List stacktrace +) {} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/LinkUpdate.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/LinkUpdate.java new file mode 100644 index 0000000..0f44607 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/LinkUpdate.java @@ -0,0 +1,6 @@ +package ru.tinkoff.edu.java.bot.api.model; + +import java.util.List; + +public record LinkUpdate(long id, String url, String description, List tgChatIds) { +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java deleted file mode 100644 index f8ef3a4..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClient.java +++ /dev/null @@ -1,97 +0,0 @@ -package ru.tinkoff.edu.java.bot.client; - -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.web.reactive.function.client.WebClient; -import reactor.core.publisher.Mono; -import ru.tinkoff.edu.java.bot.dto.*; - - -public class ScrapperClient { - - private final WebClient webClient; - - - //По умолчанию - webClient инжектится из ClientConfiguration c baseUrl по умолчанию - public ScrapperClient(WebClient webClient) { - this.webClient = webClient; - } - - //Здесь webClient не инжектится, чтобы была возможность указать baseUrl. - public ScrapperClient(String baseUrl) { - this.webClient = WebClient.create(baseUrl); - } - - - public ListLinkResponse getLinks(Long tgChatId) { - ListLinkResponse response = webClient.get().uri("/links").header("Tg-Chat-Id", String.valueOf(tgChatId)).exchangeToMono(r -> { - if (r.statusCode().equals(HttpStatus.NOT_FOUND)) { - throw new ScrapperClientException("Чат с таким ID не зарегистрирован"); - } else if (r.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) { - throw new ScrapperClientException("Что-то пошло не так. Проблема на нашей стороне, повторите попытку позже"); - } - return r.bodyToMono(ListLinkResponse.class); - }).block(); - - return response; - } - - public LinkResponse addLink(Long tgChatId, AddLinkRequest request) { - LinkResponse response = webClient.post().uri("/links").header("Tg-Chat-Id", String.valueOf(tgChatId)) - .bodyValue(request).exchangeToMono(r -> { - if (r.statusCode().equals(HttpStatus.BAD_REQUEST)) { - throw new ScrapperClientException("Ссылка с таким URL уже добавлена"); - } else if (r.statusCode().equals(HttpStatus.NOT_FOUND)) { - throw new ScrapperClientException("Чат с таким ID не зарегистрирован"); - } else if (r.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) { - throw new ScrapperClientException("Что-то пошло не так. Проблема на нашей стороне, повторите попытку позже"); - } - return r.bodyToMono(LinkResponse.class); - }).block(); - - return response; - } - - public LinkResponse deleteLink(Long tgChatId, RemoveLinkRequest request) { - LinkResponse response = webClient.method(HttpMethod.DELETE).uri("/links").header("Tg-Chat-Id", String.valueOf(tgChatId)) - .bodyValue(request).exchangeToMono(r -> { - if (r.statusCode().equals(HttpStatus.BAD_REQUEST)) { - throw new ScrapperClientException("Некорректно указана ссылка"); - } else if (r.statusCode().equals(HttpStatus.NOT_FOUND)) { - throw new ScrapperClientException("Ссылка с таким URL не найдена или чат с таким ID не зарегистрирован"); - } else if (r.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) { - throw new ScrapperClientException("Что-то пошло не так. Проблема на нашей стороне, повторите попытку позже"); - } - return r.bodyToMono(LinkResponse.class); - }).block(); - - return response; - } - - - public void registerChat(Long tgChatId, UserAddDto userAddDto) { - webClient.post().uri("/tg-chat/{id}", tgChatId).bodyValue(userAddDto).exchangeToMono(response -> { - if (response.statusCode().equals(HttpStatus.BAD_REQUEST)) { - throw new ScrapperClientException("Некорректно указан ID или такой чат уже зарегистрирован"); - } else if (response.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) { - throw new ScrapperClientException("Что-то пошло не так. Проблема на нашей стороне, повторите попытку позже"); - } - return Mono.empty(); - }).block(); - } - - public void deleteChat(Long tgChatId) { - webClient.delete().uri("/tg-chat/{id}", tgChatId).exchangeToMono(response -> { - if (response.statusCode().equals(HttpStatus.BAD_REQUEST)) { - throw new ScrapperClientException("Некорректно указан ID"); - } else if (response.statusCode().equals(HttpStatus.NOT_FOUND)) { - throw new ScrapperClientException("Чат с таким ID не найден"); - } else if (response.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) { - throw new ScrapperClientException("Что-то пошло не так. Проблема на нашей стороне, повторите попытку позже"); - } - return Mono.empty(); - }).block(); - } - - -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java deleted file mode 100644 index 9ef91d4..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/client/ScrapperClientException.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.tinkoff.edu.java.bot.client; - -public class ScrapperClientException extends RuntimeException{ - - public ScrapperClientException() { - } - - public ScrapperClientException(String message) { - super(message); - } -} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java deleted file mode 100644 index a179c88..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/Command.java +++ /dev/null @@ -1,20 +0,0 @@ -package ru.tinkoff.edu.java.bot.commands; - -import com.pengrad.telegrambot.model.Update; -import ru.tinkoff.edu.java.bot.dto.BotCommand; - -public interface Command { - String command(); - - String description(); - - String handle(Update update); - - default boolean supports(Update update) { - return update.message().text().equals(command()); - } - - default BotCommand toApiCommand() { - return new BotCommand(command(), description()); - } -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java deleted file mode 100644 index 1d3852c..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/CommandsEnum.java +++ /dev/null @@ -1,33 +0,0 @@ -package ru.tinkoff.edu.java.bot.commands; - -import java.util.HashMap; -import java.util.Map; - -public enum CommandsEnum { - - START ("/start"), - HELP ("/help"), - LIST ("/list"), - TRACK ("/track"), - UNTRACK ("/untrack"); - - private static final Map BY_LABEL = new HashMap<>(); - - static { - for (CommandsEnum c : values()) { - BY_LABEL.put(c.label, c); - } - } - - private final String label; - - CommandsEnum(String command) { - this.label = command; - } - - public static CommandsEnum valueOfLabel(String label) { - return BY_LABEL.get(label); - } - - -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java deleted file mode 100644 index 3849dc7..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/HelpCommand.java +++ /dev/null @@ -1,23 +0,0 @@ -package ru.tinkoff.edu.java.bot.commands; - -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.request.SendMessage; -import org.springframework.stereotype.Component; - -@Component -public class HelpCommand implements Command{ - @Override - public String command() { - return "/help"; - } - - @Override - public String description() { - return "ввывести окно с командами"; - } - - @Override - public String handle(Update update) { - return "Help is executing..."; - } -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java deleted file mode 100644 index 6a3176e..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/ListCommand.java +++ /dev/null @@ -1,48 +0,0 @@ -package ru.tinkoff.edu.java.bot.commands; - -import com.pengrad.telegrambot.model.Update; -import org.springframework.stereotype.Component; -import ru.tinkoff.edu.java.bot.client.ScrapperClient; -import ru.tinkoff.edu.java.bot.client.ScrapperClientException; -import ru.tinkoff.edu.java.bot.dto.Link; -import ru.tinkoff.edu.java.bot.dto.ListLinkResponse; - -@Component -public class ListCommand implements Command { - - private final ScrapperClient scrapperClient; - - public ListCommand(ScrapperClient scrapperClient) { - this.scrapperClient = scrapperClient; - } - - @Override - public String command() { - return "/list"; - } - - @Override - public String description() { - return "показать список отслеживаемых ссылок"; - } - - @Override - public String handle(Update update) { - long chatId = update.message().chat().id(); - try { - ListLinkResponse response = scrapperClient.getLinks(chatId); - StringBuilder msg = new StringBuilder(); - if (response.size() == 0) - msg.append("Список отслеживаемых ссылок пуст!"); - else { - msg.append("Ссылок отслеживается - ").append(response.size()).append("\n\n"); - for (Link link : response.links()) { - msg.append(link.url()).append("\n\n"); - } - } - return msg.toString(); - } catch (ScrapperClientException e){ - return e.getMessage(); - } - } -} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java deleted file mode 100644 index 9c9f497..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/StartCommand.java +++ /dev/null @@ -1,55 +0,0 @@ -package ru.tinkoff.edu.java.bot.commands; - -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.model.request.InlineKeyboardButton; -import com.pengrad.telegrambot.model.request.InlineKeyboardMarkup; -import com.pengrad.telegrambot.request.SendMessage; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; -import org.springframework.web.reactive.function.client.WebClient; -import reactor.core.publisher.Mono; -import ru.tinkoff.edu.java.bot.client.ScrapperClient; -import ru.tinkoff.edu.java.bot.client.ScrapperClientException; -import ru.tinkoff.edu.java.bot.dto.Link; -import ru.tinkoff.edu.java.bot.dto.ListLinkResponse; -import ru.tinkoff.edu.java.bot.dto.UserAddDto; - -@Component -public class StartCommand implements Command { - - private final ScrapperClient scrapperClient; - - public StartCommand(ScrapperClient scrapperClient) { - this.scrapperClient = scrapperClient; - } - - - @Value("${tg.bot.token}") - private String token; - - - @Override - public String command() { - return "/start"; - } - - @Override - public String description() { - return "зарегистрировать пользователя"; - } - - @Override - public String handle(Update update) { - long chatId = update.message().chat().id(); - try { - UserAddDto userAddDto = new UserAddDto(update.message().chat().username(), update.message().chat().firstName(), update.message().chat().lastName()); - scrapperClient.registerChat(chatId, userAddDto); - return "Привет! Рад познакомиться, " + update.message().chat().firstName(); - } catch (ScrapperClientException e) { - - return e.getMessage(); - } - - - } -} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java deleted file mode 100644 index a3eb9b4..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/TrackCommand.java +++ /dev/null @@ -1,47 +0,0 @@ -package ru.tinkoff.edu.java.bot.commands; - -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.request.SendMessage; -import org.springframework.stereotype.Component; -import ru.tinkoff.edu.java.link_parser.parser.Link_Parser; -import ru.tinkoff.edu.java.bot.client.ScrapperClient; -import ru.tinkoff.edu.java.bot.client.ScrapperClientException; -import ru.tinkoff.edu.java.bot.dto.AddLinkRequest; - -@Component -public class TrackCommand implements Command { - - private final LinkParser parser; - - public TrackCommand(ScrapperClient scrapperClient, LinkParser parser) { - this.scrapperClient = scrapperClient; - this.parser = parser; - } - - private final ScrapperClient scrapperClient; - - @Override - public String command() { - return "/track"; - } - - @Override - public String description() { - return "начать отслеживание ссылки"; - } - - @Override - public String handle(Update update) { - long chatId = update.message().chat().id(); - String msg; - try { - if (parser.parseUrl(update.message().text()) != null){ - scrapperClient.addLink(chatId, new AddLinkRequest(update.message().text())); - msg = "Ссылка успешно добавлена"; - } else msg = "Некорректная ссылка"; - return msg; - } catch (ScrapperClientException e) { - return e.getMessage(); - } - } -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java deleted file mode 100644 index df1c58a..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/commands/UntrackCommand.java +++ /dev/null @@ -1,49 +0,0 @@ -package ru.tinkoff.edu.java.bot.commands; - -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.request.SendMessage; -import org.springframework.stereotype.Component; -import ru.tinkoff.edu.java.link_parser.parser.Link_Parser; -import ru.tinkoff.edu.java.bot.client.ScrapperClient; -import ru.tinkoff.edu.java.bot.client.ScrapperClientException; -import ru.tinkoff.edu.java.bot.dto.AddLinkRequest; -import ru.tinkoff.edu.java.bot.dto.RemoveLinkRequest; - -@Component -public class UntrackCommand implements Command{ - - private final ScrapperClient scrapperClient; - - private final Link_Parser parser; - - - public UntrackCommand(ScrapperClient scrapperClient, Link_Parser parser) { - this.scrapperClient = scrapperClient; - this.parser = parser; - } - - @Override - public String command() { - return "/untrack"; - } - - @Override - public String description() { - return "прекратить отслеживание ссылки"; - } - - @Override - public String handle(Update update) { - long chatId = update.message().chat().id(); - String msg; - try { - if (parser.parseUrl(update.message().text()) != null){ - scrapperClient.deleteLink(chatId, new RemoveLinkRequest(update.message().text())); - msg = "Ссылка успешно удалена"; - } else msg = "Некорректная ссылка"; - return msg; - } catch (ScrapperClientException e) { - return e.getMessage(); - } - } -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java index 02ab1d4..49ce5e3 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java @@ -2,11 +2,17 @@ import jakarta.validation.constraints.NotNull; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.validation.annotation.Validated; +import ru.tinkoff.edu.java.bot.configuration.configRecords.Bot; +import ru.tinkoff.edu.java.bot.configuration.configRecords.Scheduler; @Validated +@EnableScheduling @ConfigurationProperties(prefix = "app", ignoreUnknownFields = false) -public record ApplicationConfig(@NotNull String test, - String queueName, - String exchangeName, - String routingKey) {} \ No newline at end of file +public record ApplicationConfig( + @NotNull String test, + @NotNull Scheduler scheduler, + Bot bot +) { +} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java deleted file mode 100644 index d20e877..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/BotConfiguration.java +++ /dev/null @@ -1,66 +0,0 @@ -package ru.tinkoff.edu.java.bot.configuration; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpStatus; -import org.springframework.web.reactive.function.client.WebClient; -import reactor.core.publisher.Mono; -import ru.tinkoff.edu.java.bot.commands.*; -import ru.tinkoff.edu.java.bot.dto.BotCommand; -import ru.tinkoff.edu.java.bot.dto.SetCommandRequest; -import ru.tinkoff.edu.java.bot.telegram.Bot; - -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.List; - -@Configuration -@Slf4j -public class BotConfiguration { - - @Value("${tg.bot.token}") - private String token; - - @Value("${tg.api.baseUrl}") - private String tgApiBaseUrl; - - private final HelpCommand helpCommand; - private final StartCommand startCommand; - private final ListCommand listCommand; - private final TrackCommand trackCommand; - private final UntrackCommand untrackCommand; - - public BotConfiguration(HelpCommand helpCommand, StartCommand startCommand, ListCommand listCommand, TrackCommand trackCommand, UntrackCommand untrackCommand) { - this.helpCommand = helpCommand; - this.startCommand = startCommand; - this.listCommand = listCommand; - this.trackCommand = trackCommand; - this.untrackCommand = untrackCommand; - } - - @Bean - public Bot bot() { - EnumMap commands = new EnumMap<>(CommandsEnum.class); - - - commands.put(CommandsEnum.HELP,helpCommand); - commands.put(CommandsEnum.LIST,listCommand); - commands.put(CommandsEnum.START,startCommand); - commands.put(CommandsEnum.TRACK,trackCommand); - commands.put(CommandsEnum.UNTRACK,untrackCommand); - - List apiCommands = new ArrayList<>(commands.values().stream().map(Command::toApiCommand).toList()); - WebClient botConfClient = WebClient.create(tgApiBaseUrl+token); - botConfClient.post().uri("/setMyCommands").bodyValue(new SetCommandRequest(apiCommands)).exchangeToMono(r ->{ - if (!r.statusCode().equals(HttpStatus.OK)){ - log.warn("Похоже, что API Telegram недоступен("); - } - return Mono.empty(); - }).block(); - - return new Bot(token, commands); - } - -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java deleted file mode 100644 index f5d3a09..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ClientConfiguration.java +++ /dev/null @@ -1,27 +0,0 @@ -package ru.tinkoff.edu.java.bot.configuration; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.reactive.function.client.WebClient; -import ru.tinkoff.edu.java.bot.client.ScrapperClient; - - -@Configuration -public class ClientConfiguration { - - @Value("${scrapper.baseurl}") - private String scrapperBaseUrl; - - - @Bean - public WebClient webClient(){ - return WebClient.create(scrapperBaseUrl); - } - - //Регистрируем клиентов как бины - @Bean - public ScrapperClient scrapperClient() { - return new ScrapperClient(scrapperBaseUrl); - } -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java deleted file mode 100644 index 962ff14..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/LinkParserConfiguration.java +++ /dev/null @@ -1,14 +0,0 @@ -package ru.tinkoff.edu.java.bot.configuration; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import parser.LinkParser; - -@Configuration -public class LinkParserConfiguration { - - @Bean - public LinkParser linkParser(){ - return new LinkParser(); - } -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java index 3f53ca7..b944fc5 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java @@ -7,9 +7,7 @@ import org.springframework.amqp.support.converter.MessageConverter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import ru.tinkoff.edu.java.bot.dto.LinkUpdate; -import ru.tinkoff.edu.java.bot.service.ScrapperQueueListener; -import ru.tinkoff.edu.java.bot.service.UpdateService; +import ru.tinkoff.edu.java.bot.api.model.LinkUpdate; import java.util.HashMap; import java.util.Map; @@ -55,10 +53,10 @@ Binding dlqBinding(Queue deadLetterQueue, DirectExchange exchange) { @Bean public ClassMapper classMapper() { Map> mappings = new HashMap<>(); - mappings.put("ru.tinkoff.edu.java.scrapper.dto.LinkUpdate", LinkUpdate.class); + mappings.put("ru.tinkoff.edu.java.bot.api.model.LinkUpdate", LinkUpdate.class); DefaultClassMapper classMapper = new DefaultClassMapper(); - classMapper.setTrustedPackages("ru.tinkoff.edu.java.scrapper.dto.*"); + classMapper.setTrustedPackages("ru.tinkoff.edu.java.bot.api.model.*"); classMapper.setIdClassMapping(mappings); return classMapper; } diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Bot.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Bot.java new file mode 100644 index 0000000..37f4842 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Bot.java @@ -0,0 +1,4 @@ +package ru.tinkoff.edu.java.bot.configuration.configRecords; + +public record Bot(String token, String name) { +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Scheduler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Scheduler.java new file mode 100644 index 0000000..08278f6 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Scheduler.java @@ -0,0 +1,5 @@ +package ru.tinkoff.edu.java.bot.configuration.configRecords; + +import java.time.Duration; + +public record Scheduler(Duration interval) {} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java deleted file mode 100644 index 1ff0bee..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/AddLinkRequest.java +++ /dev/null @@ -1,6 +0,0 @@ -package ru.tinkoff.edu.java.bot.dto; - - -public record AddLinkRequest(String link) { - -} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java deleted file mode 100644 index d8d6113..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ApiErrorResponse.java +++ /dev/null @@ -1,7 +0,0 @@ -package ru.tinkoff.edu.java.bot.dto; - -public record ApiErrorResponse(String description, String code, String exceptionName, - String exceptionMessage, String[] stacktrace) { - - -} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java deleted file mode 100644 index 201c5c6..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/BotCommand.java +++ /dev/null @@ -1,8 +0,0 @@ -package ru.tinkoff.edu.java.bot.dto; - -import com.fasterxml.jackson.annotation.JsonProperty; -import java.io.Serializable; - -public record BotCommand(@JsonProperty("command") String command, @JsonProperty("description") String description) implements Serializable { - -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java deleted file mode 100644 index 2ab0a84..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/Link.java +++ /dev/null @@ -1,10 +0,0 @@ -package ru.tinkoff.edu.java.bot.dto; - -import java.net.URI; - -public record Link (Long id, URI url){ - @Override - public String toString() { - return "Link{" + "id=" + id + ", url='" + url + '\'' +'}'; - } -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java deleted file mode 100644 index 396f750..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkResponse.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.tinkoff.edu.java.bot.dto; - -import java.net.URI; - -public record LinkResponse(long id, URI url) { - - @Override - public String toString() { - return "LinkResponse{" + "id=" + id + ", url=" + url +'}'; - } -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java deleted file mode 100644 index 8a92e00..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/LinkUpdate.java +++ /dev/null @@ -1,5 +0,0 @@ -package ru.tinkoff.edu.java.bot.dto; - -public record LinkUpdate(Long id, String url, String description, Long[] tgChatIds) { - -} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java deleted file mode 100644 index 5d23d7b..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/ListLinkResponse.java +++ /dev/null @@ -1,6 +0,0 @@ -package ru.tinkoff.edu.java.bot.dto; - -import java.util.List; - -public record ListLinkResponse(List links, int size) { -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java deleted file mode 100644 index 7e58ba4..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/RemoveLinkRequest.java +++ /dev/null @@ -1,5 +0,0 @@ -package ru.tinkoff.edu.java.bot.dto; - -public record RemoveLinkRequest(String link) { - -} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java deleted file mode 100644 index 799cdc3..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/SetCommandRequest.java +++ /dev/null @@ -1,7 +0,0 @@ -package ru.tinkoff.edu.java.bot.dto; - -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -public record SetCommandRequest(@JsonProperty("commands") List commands) { -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java deleted file mode 100644 index d21ec6a..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/dto/UserAddDto.java +++ /dev/null @@ -1,8 +0,0 @@ -package ru.tinkoff.edu.java.bot.dto; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public record UserAddDto(@JsonProperty("username") String username, - @JsonProperty("first_name") String firstName, - @JsonProperty("last_name") String lastName) { -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java deleted file mode 100644 index 524f6f3..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/ChatNotFoundException.java +++ /dev/null @@ -1,10 +0,0 @@ -package ru.tinkoff.edu.java.bot.exceptions; - -public class ChatNotFoundException extends RuntimeException { - public ChatNotFoundException() { - } - - public ChatNotFoundException(String message) { - super(message); - } -} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java deleted file mode 100644 index 98c36ae..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/exceptions/LinkIsNotRegisteredToChatException.java +++ /dev/null @@ -1,10 +0,0 @@ -package ru.tinkoff.edu.java.bot.exceptions; - -public class LinkIsNotRegisteredToChatException extends RuntimeException { - public LinkIsNotRegisteredToChatException() { - } - - public LinkIsNotRegisteredToChatException(String message) { - super(message); - } -} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/BotMain.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/BotMain.java new file mode 100644 index 0000000..f758472 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/BotMain.java @@ -0,0 +1,36 @@ +package ru.tinkoff.edu.java.bot.firstBot; + +import com.pengrad.telegrambot.TelegramBot; +import com.pengrad.telegrambot.request.SendMessage; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import ru.tinkoff.edu.java.bot.configuration.ApplicationConfig; + + +@EnableConfigurationProperties(ApplicationConfig.class) +public class BotMain { + + String token; + static TelegramBot bot; + + public BotMain(String token) { + this.token = token; + } + + public void start() { + bot = new TelegramBot(token); + bot.setUpdatesListener(new Updater(bot)); + } + + public void end() { + bot.removeGetUpdatesListener(); + } + + public static void apiCommand(long tgChatId, String command) { + + MessageHandler handler = new MessageHandler(); + String[] parse = command.split(" "); + if(parse.length > 1) command = handler.call_command(parse[0], parse[1]); + else command = handler.call_command(parse[0]); + bot.execute(new SendMessage(tgChatId, command)); + } +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/DB.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/DB.java new file mode 100644 index 0000000..486a886 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/DB.java @@ -0,0 +1,42 @@ +package ru.tinkoff.edu.java.bot.firstBot; + +import java.util.ArrayList; + +public class DB { + + static ArrayList list = new ArrayList(); + + public static void addLink(String link) { + list.add(link); + } + + public static void rmLink(String link) { + list.remove(link); + } + + public static String getListParse() { + + int i = 1; + + String out_list = ""; + + for(String element: list){ + + out_list += element; + + if(i != list.size()) { + out_list += ", "; + } + i++; + } + return out_list; + } + + public static boolean listIsEmpty() { + return list.isEmpty(); + } + + public static boolean linkContain(String link) { + return list.contains(link); + } +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/MessageHandler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/MessageHandler.java new file mode 100644 index 0000000..f003c84 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/MessageHandler.java @@ -0,0 +1,30 @@ +package ru.tinkoff.edu.java.bot.firstBot; + +import ru.tinkoff.edu.java.bot.firstBot.commands.All; + +public class MessageHandler extends All { + + public boolean is_command(String message) { + return message.startsWith("/"); + } + + public String call_command(String command, String arg) { + return switch (command) { + case "/start" -> start(); + case "/help" -> help(); + case "/track" -> track(arg); + case "/list" -> list(); + case "/untrack" -> untrack(arg); + default -> unknow(); + }; + } + + public String call_command(String command) { + return switch (command) { + case "/start" -> start(); + case "/help" -> help(); + case "/list" -> list(); + default -> unknow(); + }; + } +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/Updater.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/Updater.java new file mode 100644 index 0000000..a01e4d9 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/Updater.java @@ -0,0 +1,39 @@ +package ru.tinkoff.edu.java.bot.firstBot; + +import com.pengrad.telegrambot.TelegramBot; +import com.pengrad.telegrambot.UpdatesListener; +import com.pengrad.telegrambot.model.Update; +import com.pengrad.telegrambot.model.request.*; +import com.pengrad.telegrambot.request.SendMessage; + +import java.util.List; + +public class Updater implements UpdatesListener { + + MessageHandler handler = new MessageHandler(); + String command; + TelegramBot bot; + + public Updater(TelegramBot bot) { + this.bot = bot; + } + + @Override + public int process(List updates) { + Update update = updates.get(0); + if(handler.is_command(update.message().text())) { + String[] parse = update.message().text().split(" "); + if(parse.length > 1) command = handler.call_command(parse[0], parse[1]); + else command = handler.call_command(parse[0]); + bot.execute( + new SendMessage(update.message().chat().id(), command) + .replyMarkup(new ReplyKeyboardMarkup(new String[][]{ + {"/start", "/help"}, + {"/track testlink", "/untrack testlink", "/list"} + }).resizeKeyboard(true) + ).parseMode(ParseMode.HTML) + ); + } + return UpdatesListener.CONFIRMED_UPDATES_ALL; + } +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/All.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/All.java new file mode 100644 index 0000000..991b177 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/All.java @@ -0,0 +1,7 @@ +package ru.tinkoff.edu.java.bot.firstBot.commands; + +public class All implements List, Start, Track, Untrack, Help { + protected String unknow() { + return "Неизвестная команда"; + } +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Help.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Help.java new file mode 100644 index 0000000..0761e05 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Help.java @@ -0,0 +1,11 @@ +package ru.tinkoff.edu.java.bot.firstBot.commands; + +public interface Help { + default String help() { + return "/start -- зарегистрировать пользователя\n" + + "/help -- вывести окно с командами\n" + + "/track [link] -- начать отслеживание ссылки\n" + + "/untrack [link] -- прекратить отслеживание ссылки\n" + + "/list -- показать список отслеживаемых ссылок"; + } +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/List.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/List.java new file mode 100644 index 0000000..8673887 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/List.java @@ -0,0 +1,10 @@ +package ru.tinkoff.edu.java.bot.firstBot.commands; + +import ru.tinkoff.edu.java.bot.firstBot.DB; + +public interface List { + default String list() { + if(DB.listIsEmpty()) return "list пустой"; + return "Отслеживаемые ссылки: " + DB.getListParse() + ""; + } +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Start.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Start.java new file mode 100644 index 0000000..d58c89c --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Start.java @@ -0,0 +1,9 @@ +package ru.tinkoff.edu.java.bot.firstBot.commands; + +public interface Start { + + default String start() { + return "Бот начал работу"; + } +} + diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Track.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Track.java new file mode 100644 index 0000000..0f4669e --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Track.java @@ -0,0 +1,13 @@ +package ru.tinkoff.edu.java.bot.firstBot.commands; + +import ru.tinkoff.edu.java.bot.firstBot.DB; + +public interface Track { + default String track(String link) { + link = link.trim(); + if(link.equals("")) return "ведите ссылку"; + if(DB.linkContain(link)) return "Ссылка уже есть"; + DB.addLink(link); + return "ссылка " + link + " добавлена"; + } +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Untrack.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Untrack.java new file mode 100644 index 0000000..6550daf --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Untrack.java @@ -0,0 +1,14 @@ +package ru.tinkoff.edu.java.bot.firstBot.commands; + +import ru.tinkoff.edu.java.bot.firstBot.DB; + +public interface Untrack { + default String untrack(String link) { + if(link.equals("")) return "ведите ссылку"; + if(DB.linkContain(link)) { + DB.rmLink(link); + return "ссылка " + link + " удалена"; + } + return "ссылки " + link + " нет в пуле"; + } +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java deleted file mode 100644 index 604e19c..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/rest/BotRestController.java +++ /dev/null @@ -1,30 +0,0 @@ -package ru.tinkoff.edu.java.bot.rest; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import ru.tinkoff.edu.java.bot.dto.LinkUpdate; -import ru.tinkoff.edu.java.bot.service.UpdateService; -import ru.tinkoff.edu.java.bot.service.UpdateServiceImpl; - -@RestController -@Slf4j -public class BotRestController { - - - private final UpdateService updateService; - - - public BotRestController(UpdateService updateService) { - this.updateService = updateService; - } - - @PostMapping("updates") - public void sendUpdate(@RequestBody LinkUpdate request) { - log.info("Пришёл запрос на обновление: "+request); - updateService.updateLink(request); - } - - -} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/schedule/LinkUpdaterScheduler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/schedule/LinkUpdaterScheduler.java new file mode 100644 index 0000000..1b2ff0f --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/schedule/LinkUpdaterScheduler.java @@ -0,0 +1,17 @@ +package ru.tinkoff.edu.java.bot.schedule; + +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +import java.util.logging.Level; +import java.util.logging.Logger; + +@Service +public class LinkUpdaterScheduler { + private final static Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + + @Scheduled(fixedDelayString = "${app.scheduler.interval}") + public void update() { + LOGGER.log(Level.INFO, "Info bot called"); + } +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java deleted file mode 100644 index ed22af0..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateService.java +++ /dev/null @@ -1,8 +0,0 @@ -package ru.tinkoff.edu.java.bot.service; - -import ru.tinkoff.edu.java.bot.dto.LinkUpdate; - -public interface UpdateService { - -void updateLink(LinkUpdate linkUpdate); -} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java deleted file mode 100644 index f3878a4..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/UpdateServiceImpl.java +++ /dev/null @@ -1,26 +0,0 @@ -package ru.tinkoff.edu.java.bot.service; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import ru.tinkoff.edu.java.bot.dto.LinkUpdate; -import ru.tinkoff.edu.java.bot.telegram.Bot; - -@Service -@Slf4j -public class UpdateServiceImpl implements UpdateService{ - - private final Bot bot; - - public UpdateServiceImpl(Bot bot) { - this.bot = bot; - } - - public void updateLink(LinkUpdate linkUpdate) { - log.info("updateLink() method invocation in UpdateServiceImpl"); - String message = "Вышло обновление по ссылке "+linkUpdate.url()+" \n"+linkUpdate.description(); - for (Long chatId : linkUpdate.tgChatIds()) { - bot.sendMessage(chatId, message); - } - } - -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java deleted file mode 100644 index 50c8671..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/Bot.java +++ /dev/null @@ -1,53 +0,0 @@ -package ru.tinkoff.edu.java.bot.telegram; - -import com.pengrad.telegrambot.TelegramBot; -import com.pengrad.telegrambot.UpdatesListener; -import com.pengrad.telegrambot.model.Update; -import com.pengrad.telegrambot.request.SendMessage; -import jakarta.annotation.PostConstruct; -import ru.tinkoff.edu.java.bot.commands.Command; -import ru.tinkoff.edu.java.bot.commands.CommandsEnum; - -import java.util.EnumMap; - -public class Bot implements AutoCloseable { - - private final TelegramBot bot; - private final UserMessageProcessor userMessageProcessor; - - - - @PostConstruct - public void init(){ - start(); - } - - public Bot(String token, EnumMap commands) { - System.out.println("Создание бота... Токен: " + token); - userMessageProcessor = new UserMessageProcessor(commands); - bot = new TelegramBot(token); - } - - public void start() { - System.out.println("Бот запущен..."); - bot.setUpdatesListener(updates -> { - for (Update update : updates) { - bot.execute(new SendMessage(update.message().chat().id(), userMessageProcessor.process(update))); - - } - return UpdatesListener.CONFIRMED_UPDATES_ALL; - }); - } - - - public void sendMessage(Long chatId, String msg) { - bot.execute(new SendMessage(chatId, msg)); - } - - - - @Override - public void close() throws Exception { - bot.removeGetUpdatesListener(); - } -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java deleted file mode 100644 index fb08682..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserMessageProcessor.java +++ /dev/null @@ -1,67 +0,0 @@ -package ru.tinkoff.edu.java.bot.telegram; - -import com.pengrad.telegrambot.model.Update; -import ru.tinkoff.edu.java.bot.commands.*; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.Map; - - -public class UserMessageProcessor { - - private final Map userStateMap; - - private final EnumMap commands; - - - public UserMessageProcessor(EnumMap commands) { - this.commands = commands; - userStateMap = new HashMap<>(); - } - - public String process(Update update) { - Command command; - - - userStateMap.putIfAbsent(update.message().chat().id(), UserState.TYPING_COMMAND); - switch (userStateMap.get(update.message().chat().id())) { - case TYPING_TRACKED -> { - userStateMap.put(update.message().chat().id(), UserState.TYPING_COMMAND); - return commands.get(CommandsEnum.valueOfLabel("/track")).handle(update); - } - case TYPING_UNTRACKED -> { - userStateMap.put(update.message().chat().id(), UserState.TYPING_COMMAND); - return commands.get(CommandsEnum.valueOfLabel("/untrack")).handle(update); - } - case TYPING_COMMAND -> { - userStateMap.put(update.message().chat().id(), UserState.TYPING_COMMAND); - command = commands.get(CommandsEnum.valueOfLabel(update.message().text())); - if (command == null) - return "Неизвестная команда. Нажмите 'Меню' чтобы посмотреть список доступных команд"; - if (command instanceof TrackCommand) { - userStateMap.put(update.message().chat().id(), UserState.TYPING_TRACKED); - return "Отправьте ссылку, которую хотите начать отслеживать"; - } - if (command instanceof UntrackCommand) { - userStateMap.put(update.message().chat().id(), UserState.TYPING_UNTRACKED); - return "Отправьте ссылку, которую хотите перестать отслеживать"; - } - if (command instanceof HelpCommand){ - StringBuilder text = new StringBuilder(); - for (Command c : commands.values()) { - text.append(c.command()).append(" - ").append(c.description()).append("\n"); - } - return text.toString(); - } - return command.handle(update); - } - default -> { - - return "Что-то пошло не так. Проблема на нашеё стороне"; - } - } - - } - - -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java deleted file mode 100644 index 70bc584..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/telegram/UserState.java +++ /dev/null @@ -1,5 +0,0 @@ -package ru.tinkoff.edu.java.bot.telegram; - -public enum UserState { - TYPING_COMMAND, TYPING_TRACKED, TYPING_UNTRACKED -} diff --git a/FP/bot/src/main/resources/application.properties b/FP/bot/src/main/resources/application.properties index 9f20e72..fedebeb 100644 --- a/FP/bot/src/main/resources/application.properties +++ b/FP/bot/src/main/resources/application.properties @@ -1,13 +1,6 @@ -app.test=beamer-bot -server.port=8080 +app.test=123 springdoc.swagger-ui.path=/swagger-ui -tg.bot.token=${TGBOTTOKEN} -tg.api.baseUrl=https://api.telegram.org/bot -spring.rabbitmq.host=localhost -spring.rabbitmq.port=5672 -spring.rabbitmq.username=romanova -spring.rabbitmq.password=12345654321 -spring.rabbitmq.listener.simple.default-requeue-rejected=false -app.queue-name=scrapper-bot-queue -app.exchange-name=scrapper-bot-exchange -app.routing-key=scrapper-bot-key \ No newline at end of file +app.scheduler.interval=50000 +app.bot.token=5805337447:AAGnmh2isW2115L7tJWFojbpmSjNrarTvxQ +app.bot.name=@SFRETbot +server.port=8081 diff --git a/FP/bot/src/main/resources/botapi.yml b/FP/bot/src/main/resources/botapi.yml new file mode 100644 index 0000000..489441e --- /dev/null +++ b/FP/bot/src/main/resources/botapi.yml @@ -0,0 +1,59 @@ +openapi: 3.0.1 +info: + title: Bot API + version: 1.0.0 + contact: + name: Alexander Biryukov + url: https://github.com +paths: + /updates: + post: + summary: Отправить обновление + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/LinkUpdate' + required: true + responses: + '200': + description: Обновление обработано + '400': + description: Некорректные параметры запроса + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorResponse' +components: + schemas: + ApiErrorResponse: + type: object + properties: + description: + type: string + code: + type: string + exceptionName: + type: string + exceptionMessage: + type: string + stacktrace: + type: array + items: + type: string + LinkUpdate: + type: object + properties: + id: + type: integer + format: int64 + url: + type: string + format: uri + description: + type: string + tgChatIds: + type: array + items: + type: integer + format: int64 diff --git a/FP/bot/src/test/java/BotTest.java b/FP/bot/src/test/java/BotTest.java new file mode 100644 index 0000000..1548bc9 --- /dev/null +++ b/FP/bot/src/test/java/BotTest.java @@ -0,0 +1,24 @@ +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import ru.tinkoff.edu.java.bot.firstBot.DB; +import ru.tinkoff.edu.java.bot.firstBot.MessageHandler; + + +public class BotTest { + + String except_empty_list = "list пустой"; + String except_unknow_command = "Неизвестная команда"; + MessageHandler handler = new MessageHandler(); + + @Test + public void listTest() { + Assertions.assertEquals(handler.call_command("/list"), except_empty_list); + DB.addLink("link"); + Assertions.assertNotEquals(handler.call_command("/list"), except_empty_list); + } + + @Test + public void unknowCommandAndFormatTest() { + Assertions.assertEquals(handler.call_command("/uno"), except_unknow_command); + } +} diff --git a/FP/bot/src/test/java/bot/BotTest.java b/FP/bot/src/test/java/bot/BotTest.java deleted file mode 100644 index af954d2..0000000 --- a/FP/bot/src/test/java/bot/BotTest.java +++ /dev/null @@ -1,123 +0,0 @@ -package bot; - -import com.pengrad.telegrambot.model.Chat; -import com.pengrad.telegrambot.model.Message; -import com.pengrad.telegrambot.model.Update; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; -import org.springframework.test.util.ReflectionTestUtils; -import ru.tinkoff.edu.java.bot.client.ScrapperClient; -import ru.tinkoff.edu.java.bot.commands.Command; -import ru.tinkoff.edu.java.bot.commands.CommandsEnum; -import ru.tinkoff.edu.java.bot.commands.ListCommand; -import ru.tinkoff.edu.java.bot.dto.Link; -import ru.tinkoff.edu.java.bot.dto.ListLinkResponse; -import ru.tinkoff.edu.java.bot.telegram.UserMessageProcessor; -import ru.tinkoff.edu.java.bot.telegram.UserState; - -import java.net.URI; -import java.util.*; - -public class BotTest { - - static UserMessageProcessor userMessageProcessor; - - static ScrapperClient scrapperClient; - - static Update updateForListCommand; - static Update updateForInvalidCommand; - static Message messageForListCommand; - static Message messageForInvalidCommand; - - static Chat chat; - - @BeforeAll - static void init() { - //инициализируем заглушки и входные дынные, т.к. у Update в нет сеттеров, то используем рефлексию, - //чтобы поместить туда нужный Message - scrapperClient = Mockito.mock(ScrapperClient.class); - updateForListCommand = new Update(); - messageForListCommand = new Message(); - chat = new Chat(); - ReflectionTestUtils.setField(chat, "id", 42L); - ReflectionTestUtils.setField(messageForListCommand, "chat", chat); - ReflectionTestUtils.setField(messageForListCommand, "text", "/list"); - ReflectionTestUtils.setField(updateForListCommand, "message", messageForListCommand); - - updateForInvalidCommand = new Update(); - messageForInvalidCommand = new Message(); - - ReflectionTestUtils.setField(messageForInvalidCommand, "chat", chat); - ReflectionTestUtils.setField(messageForInvalidCommand, "text", "Azazelo"); - ReflectionTestUtils.setField(updateForInvalidCommand, "message", messageForInvalidCommand); - } - - @Test - @DisplayName("Тест команды /list, когда список ссылок непустой") - public void listCommandTestNotEmpty() { - - //имитируем нужное поведение клиента для Scrapper, т.к. реального запроса на Scrapper во время не происходит - List listLink = new ArrayList<>(); - listLink.add(new Link(1L, URI.create("https://github.com/lwbeamer/asm-like-language"))); - listLink.add(new Link(2L, URI.create("https://stackoverflow.com/questions/512877/why-cant-i-define-a-static-method-in-a-java-interface"))); - Mockito.when(scrapperClient.getLinks(42L)).thenReturn( - new ListLinkResponse(listLink, listLink.size()) - ); - - EnumMap map = new EnumMap<>(CommandsEnum.class); - map.put(CommandsEnum.LIST, new ListCommand(scrapperClient)); - - userMessageProcessor = new UserMessageProcessor(map); - - String expectedMessage = """ - Ссылок отслеживается - 2 - - https://github.com/lwbeamer/asm-like-language - - https://stackoverflow.com/questions/512877/why-cant-i-define-a-static-method-in-a-java-interface - - """; - - Assertions.assertEquals(expectedMessage, userMessageProcessor.process(updateForListCommand)); - } - - - @Test - @DisplayName("Тест команды /list, когда список ссылок пустой") - public void listCommandTestEmpty() { - Mockito.when(scrapperClient.getLinks(42L)).thenReturn( - new ListLinkResponse(new ArrayList<>(), 0) - ); - - - EnumMap map = new EnumMap<>(CommandsEnum.class); - map.put(CommandsEnum.LIST, new ListCommand(scrapperClient)); - - userMessageProcessor = new UserMessageProcessor(map); - - - String expectedMessage = "Список отслеживаемых ссылок пуст!"; - - Assertions.assertEquals(expectedMessage, userMessageProcessor.process(updateForListCommand)); - } - - @Test - @DisplayName("Тест для проверки ввода неизвестной команды") - public void invalidCommandCheck() { - userMessageProcessor = new UserMessageProcessor(new EnumMap<>(CommandsEnum.class)); - - //Устанавливаем состояние перед тестом - пользователь в сосвтоянии "печатает команду" - Map userStateMap = new HashMap<>(); - userStateMap.put(chat.id(), UserState.TYPING_COMMAND); - ReflectionTestUtils.setField(userMessageProcessor, "userStateMap", userStateMap); - - String expectedMessage = "Неизвестная команда. Нажмите 'Меню' чтобы посмотреть список доступных команд"; - - Assertions.assertEquals(expectedMessage, userMessageProcessor.process(updateForInvalidCommand)); - - } - -} \ No newline at end of file diff --git a/FP/docker-compose.yml b/FP/docker-compose.yml index c472659..b9f4994 100644 --- a/FP/docker-compose.yml +++ b/FP/docker-compose.yml @@ -1,60 +1,52 @@ +version: '1.-' + services: - postgresql: - image: postgres:15 - container_name: postgresql - ports: - - 5432:5432 + postgres: + container_name: postgres + image: postgres:15.2 environment: - - POSTGRES_USER=lwbeamer - - POSTGRES_PASSWORD=2281337 - - POSTGRES_DB=scrapper + POSTGRES_DB: scrapper + POSTGRES_USER: scrap_user + POSTGRES_PASSWORD: hard_password volumes: - - link-service-data:/var/lib/postgresql/data + - ./migrations/postgres_data:/var/lib/postgresql/data + ports: + - "5432:5432" networks: - backend liquibase-migrations: + container_name: liquibase image: liquibase/liquibase:4.18 - depends_on: - - postgresql + deploy: + restart_policy: + condition: on-failure + delay: 10s + max_attempts: 10 command: - --hub-mode=off - --changelog-file=master.xml - --driver=org.postgresql.Driver - - --url=jdbc:postgresql://postgresql:5432/scrapper - - --username=romanova - - --password=12345654321 + - --url=jdbc:postgresql://postgres:5432/scrapper + - --username=scrap_user + - --password=hard_password + - --logLevel=debug - update volumes: - ./migrations:/liquibase/changelog networks: - backend - -volumes: - link-service-data: - -networks: - backend: - name: backend - rabbit: - image: rabbitmq:3-management - hostname: rabbitmq - container_name: rabbit + rabbitmq: + image: rabbitmq:3-management-alpine ports: - - 15672:15672 - - 5672:5672 - environment: - - RABBITMQ_DEFAULT_USER=romanova - - RABBITMQ_DEFAULT_PASS=12345654321 + - 5672:5672 # Порт для AMQP + - 15672:15672 # Порт для RabbitMQ Management UI volumes: - - rabbitmq-state:/var/lib/rabbitmq - networks: - - backend - -volumes: - link-service-data: - rabbitmq-state: + - ./rabbitmq:/var/lib/rabbitmq + environment: + - RABBITMQ_DEFAULT_USER=root + - RABBITMQ_DEFAULT_PASS=root networks: backend: - name: backend \ No newline at end of file + driver: bridge \ No newline at end of file diff --git a/FP/link-parser/.classpath b/FP/link-parser/.classpath deleted file mode 100644 index a08fc4f..0000000 --- a/FP/link-parser/.classpath +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/FP/link-parser/.gitignore b/FP/link-parser/.gitignore deleted file mode 100644 index b83d222..0000000 --- a/FP/link-parser/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/FP/link-parser/.project b/FP/link-parser/.project deleted file mode 100644 index dec0f32..0000000 --- a/FP/link-parser/.project +++ /dev/null @@ -1,23 +0,0 @@ - - - link-parser - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - - diff --git a/FP/link-parser/.settings/org.eclipse.core.resources.prefs b/FP/link-parser/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index 29abf99..0000000 --- a/FP/link-parser/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,6 +0,0 @@ -eclipse.preferences.version=1 -encoding//src/main/java=UTF-8 -encoding//src/main/resources=UTF-8 -encoding//src/test/java=UTF-8 -encoding//src/test/resources=UTF-8 -encoding/=UTF-8 diff --git a/FP/link-parser/.settings/org.eclipse.jdt.core.prefs b/FP/link-parser/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 5e4ec05..0000000 --- a/FP/link-parser/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,9 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.methodParameters=generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 -org.eclipse.jdt.core.compiler.compliance=17 -org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore -org.eclipse.jdt.core.compiler.release=enabled -org.eclipse.jdt.core.compiler.source=17 diff --git a/FP/link-parser/.settings/org.eclipse.m2e.core.prefs b/FP/link-parser/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f..0000000 --- a/FP/link-parser/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/FP/link-parser/pom.xml b/FP/link-parser/pom.xml index 3cfd292..088df38 100644 --- a/FP/link-parser/pom.xml +++ b/FP/link-parser/pom.xml @@ -1,30 +1,26 @@ - - 4.0.0 - - project - project - 0.0.1-SNAPSHOT - - link-parser - + + + + org.example + FP + 1.0 + + + 4.0.0 + + link-parser + org.junit.jupiter - junit-jupiter-params + junit-jupiter + test + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 - - - - - - org.apache.maven.plugins - maven-failsafe-plugin - - - org.apache.maven.plugins - maven-surefire-plugin - - - - \ No newline at end of file diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/GitHub_Link.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/GitHub_Link.java deleted file mode 100644 index e244c93..0000000 --- a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/GitHub_Link.java +++ /dev/null @@ -1,5 +0,0 @@ -package ru.tinkoff.edu.java.link_parser.link; - -public record GitHub_Link(String username, String repository) implements Parser_Link { - -} \ No newline at end of file diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/Parser_Link.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/Parser_Link.java deleted file mode 100644 index 75db93c..0000000 --- a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/Parser_Link.java +++ /dev/null @@ -1,5 +0,0 @@ -package ru.tinkoff.edu.java.link_parser.link; - -public sealed interface Parser_Link permits GitHub_Link, StackOverflow_Link { - -} \ No newline at end of file diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/StackOverflow_Link.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/StackOverflow_Link.java deleted file mode 100644 index 1dad8ad..0000000 --- a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/link/StackOverflow_Link.java +++ /dev/null @@ -1,5 +0,0 @@ -package ru.tinkoff.edu.java.link_parser.link; - -public record StackOverflow_Link(long id) implements Parser_Link { - -} \ No newline at end of file diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java deleted file mode 100644 index f3641fc..0000000 --- a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Abstract.java +++ /dev/null @@ -1,27 +0,0 @@ -package ru.tinkoff.edu.java.link_parser.parser; - -import ru.tinkoff.edu.java.link_parser.link.Parser_Link; -import java.net.MalformedURLException; -import java.net.URL; - -public abstract class Abstract { - - Abstract nextParser; - - public Abstract(Abstract nextParser) { - this.nextParser = nextParser; - } - - public abstract Parser_Link parser_Link(String url); - - public final URL tweakUrl(String urlString) { - URL url; - try{ - url = new URL(urlString); - } catch (MalformedURLException e){ - System.out.println("Incorrect URL"); - return null; - } - return url; - } -} \ No newline at end of file diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java deleted file mode 100644 index 13ae325..0000000 --- a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Github.java +++ /dev/null @@ -1,31 +0,0 @@ -package ru.tinkoff.edu.java.link_parser.parser; - -import ru.tinkoff.edu.java.link_parser.link.GitHub_Link; -import ru.tinkoff.edu.java.link_parser.link.Parser_Link; - -import java.net.URL; - - -public class Github extends Abstract { - public Github(Abstract nextParser) { - super(nextParser); - } - - @Override - public Parser_Link parser_Link(String url) { - URL toParse = tweakUrl(url); - if (toParse == null) return null; - - if (toParse.getHost().equals("github.com")) { - String[] tokens = toParse.getFile().substring(1).split("/"); - if (tokens.length >= 2) { - return new GitHub_Link(tokens[0], tokens[1]); - } else return null; - } - - - if (nextParser != null) return nextParser.parser_Link(url); - - return null; - } -} \ No newline at end of file diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Link_Parser.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Link_Parser.java deleted file mode 100644 index fac1e3f..0000000 --- a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/Link_Parser.java +++ /dev/null @@ -1,16 +0,0 @@ -package ru.tinkoff.edu.java.link_parser.parser; - -import ru.tinkoff.edu.java.link_parser.parser.Abstract; -import ru.tinkoff.edu.java.link_parser.parser.Github; -import ru.tinkoff.edu.java.link_parser.parser.StackOverflow; -import ru.tinkoff.edu.java.link_parser.link.Parser_Link; - -public class Link_Parser { - public Parser_Link parseUrl(String url) { - Abstract parser1 = new Github(null); - Abstract parser2 = new StackOverflow(parser1); - - return parser2.parser_Link(url); - } - -} diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java deleted file mode 100644 index e224578..0000000 --- a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/link_parser/parser/StackOverflow.java +++ /dev/null @@ -1,34 +0,0 @@ -package ru.tinkoff.edu.java.link_parser.parser; - -import ru.tinkoff.edu.java.link_parser.link.Parser_Link; -import ru.tinkoff.edu.java.link_parser.link.StackOverflow_Link; -import java.net.URL; -public class StackOverflow extends Abstract { - public StackOverflow(Abstract nextParser) { - super(nextParser); - } - - @Override - public Parser_Link parser_Link(String url) { - - URL toParse = tweakUrl(url); - if (toParse == null) return null; - - - if (toParse.getHost().equals("stackoverflow.com")) { - String[] tokens = toParse.getFile().substring(1).split("/"); - if (tokens.length >= 2 && tokens[0].equals("questions")) { - try { - return new StackOverflow_Link(Long.parseLong(tokens[1])); - } catch (NumberFormatException e) { - System.out.println("Incorrect question ID"); - return null; - } - } else return null; - } - - if (nextParser != null) return nextParser.parser_Link(url); - - return null; - } -} \ No newline at end of file diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/LinkParser.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/LinkParser.java new file mode 100644 index 0000000..1f217ea --- /dev/null +++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/LinkParser.java @@ -0,0 +1,18 @@ +package ru.tinkoff.edu.java.linkparser; + +import ru.tinkoff.edu.java.linkparser.absracts.*; + +public class LinkParser { + + public String getLink(String link) { + + AbstractParser gitParser = new GitParser(); + AbstractParser stackParser = new StackParser(); + AbstractParser otherParser = new OtherParser(); + + gitParser.setNextParser(stackParser); + stackParser.setNextParser(otherParser); + + return gitParser.logParser(link); + } +} diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/AbstractParser.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/AbstractParser.java new file mode 100644 index 0000000..503e413 --- /dev/null +++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/AbstractParser.java @@ -0,0 +1,20 @@ +package ru.tinkoff.edu.java.linkparser.absracts; + +public abstract class AbstractParser { + + private AbstractParser nextParser; + + public void setNextParser(AbstractParser nextParser) { + this.nextParser = nextParser; + } + + public String logParser (String link) { + if(nextParser != null) { + if(this.parsAbstract(link) == null) return nextParser.logParser(link); + } + return this.parsAbstract(link); + } + + abstract protected String parsAbstract(String link); + +} diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/GitParser.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/GitParser.java new file mode 100644 index 0000000..9525306 --- /dev/null +++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/GitParser.java @@ -0,0 +1,20 @@ +package ru.tinkoff.edu.java.linkparser.absracts; + +import java.util.Objects; + +public class GitParser extends AbstractParser { + + @Override + protected String parsAbstract(String link) { + + String[] parsed = link.split("/"); + + if (parsed.length < 2) return null; + + if (!Objects.equals(parsed[2], "github.com")) return null; + + if (parsed.length > 4) return parsed[3] + "/" + parsed[4]; + + return null; + } +} diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/OtherParser.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/OtherParser.java new file mode 100644 index 0000000..f3746fe --- /dev/null +++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/OtherParser.java @@ -0,0 +1,9 @@ +package ru.tinkoff.edu.java.linkparser.absracts; + +public class OtherParser extends AbstractParser { + + @Override + protected String parsAbstract(String link) { + return null; + } +} diff --git a/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/StackParser.java b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/StackParser.java new file mode 100644 index 0000000..571ea58 --- /dev/null +++ b/FP/link-parser/src/main/java/ru/tinkoff/edu/java/linkparser/absracts/StackParser.java @@ -0,0 +1,19 @@ +package ru.tinkoff.edu.java.linkparser.absracts; + +import java.util.Objects; + +public class StackParser extends AbstractParser { + + @Override + protected String parsAbstract(String link) { + + String[] parsed = link.split("/"); + + if (parsed.length < 5) return null; + if (!Objects.equals(parsed[2], "stackoverflow.com")) return null; + if (!Objects.equals(parsed[3], "questions")) return null; + + + return parsed[4]; + } +} diff --git a/FP/link-parser/src/test/java/LinkParserTest.java b/FP/link-parser/src/test/java/LinkParserTest.java index bef7512..7bd8349 100644 --- a/FP/link-parser/src/test/java/LinkParserTest.java +++ b/FP/link-parser/src/test/java/LinkParserTest.java @@ -1,99 +1,24 @@ -import static org.junit.jupiter.api.Assertions.*; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import ru.tinkoff.edu.java.link_parser.parser.*; -import ru.tinkoff.edu.java.link_parser.link.*; +import ru.tinkoff.edu.java.linkparser.LinkParser; public class LinkParserTest { - static String validGitHubLink; - static String validStackOverflowLink; - static String gitHubNotRepoLink; - static String stackOverflowNotQuestionLink; - static String emptyLink; - static String withoutProtocolLink; - static String unknownHostLink; - static String invalidLink; - - - @BeforeAll - static void init() { - validGitHubLink = "https://github.com/lwbeamer/asm-like-language"; - validStackOverflowLink = "https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file"; - gitHubNotRepoLink = "https://github.com/issues"; - stackOverflowNotQuestionLink = "https://stackoverflow.co/talent"; - emptyLink = ""; - withoutProtocolLink = "github.com/lwbeamer/asm-like-language"; - unknownHostLink = "https://vk.com/feed"; - invalidLink = "somethingNotValid"; - } - - - @Test - @DisplayName("Тест для проверки валидной ссылки с GitHub") - void checkValidGitHubLink() { - Link_Parser parser = new Link_Parser(); - Assertions.assertEquals(new GitHub_Link("lwbeamer", "asm-like-language"), parser.parseUrl(validGitHubLink), "Тест не пройден, проверьте реузультат"); - } + String gitLink = "https://github.com/Ray-Not/JavaGuava"; + String invalidLink = "https://gitrub.com/"; + String invalidLink2 = "https://github.com/Ray-Not"; + String expectGitLink = "Ray-Not/JavaGuava"; + String stackLink = "https://stackoverflow.com/questions/1642028/what-is-the-operator-in-c"; + String expectStackLink = "1642028"; + LinkParser pars = new LinkParser(); @Test - @DisplayName("Тест для проверки валидной ссылки со StackOverflow") - void validStackOverflowLink() { - Link_Parser parser = new Link_Parser(); - Assertions.assertEquals(new StackOverflow_Link(2336692), parser.parseUrl(validStackOverflowLink), "Тест не пройден, проверьте реузультат"); + public void validGitPars(){ + Assertions.assertNull(pars.getLink(invalidLink)); + Assertions.assertNull(pars.getLink(invalidLink2)); + Assertions.assertNotNull(pars.getLink(gitLink)); + Assertions.assertEquals(pars.getLink(gitLink), expectGitLink); + Assertions.assertEquals(pars.getLink(stackLink), expectStackLink); } - - - @Test - @DisplayName("Тест для проверки ссылки с GitHub, не являющейся репозиторием") - void gitHubNotRepoLink() { - Link_Parser parser = new Link_Parser(); - Assertions.assertNull(parser.parseUrl(gitHubNotRepoLink), "Тест не пройден, проверьте реузультат"); - } - - @Test - @DisplayName("Тест для проверки ссылки со StackOverflow, не являющейся вопросом") - void stackOverflowNotQuestionLink() { - Link_Parser parser = new Link_Parser(); - Assertions.assertNull(parser.parseUrl(stackOverflowNotQuestionLink), "Тест не пройден, проверьте реузультат"); - } - - - @Test - @DisplayName("Тест для проверки пустой ссылки") - void emptyLink() { - Link_Parser parser = new Link_Parser(); - Assertions.assertNull(parser.parseUrl(emptyLink), "Тест не пройден, проверьте реузультат"); - } - - - @Test - @DisplayName("Тест для проверки ссылки без указания протокола") - void withoutProtocolLink() { - Link_Parser parser = new Link_Parser(); - Assertions.assertNull(parser.parseUrl(withoutProtocolLink), "Тест не пройден, проверьте реузультат"); - } - - @Test - @DisplayName("Тест для проверки ссылки, не относящейся к отслеживаемым ресурсам") - void unknownHostLink() { - Link_Parser parser = new Link_Parser(); - Assertions.assertNull(parser.parseUrl(unknownHostLink), "Тест не пройден, проверьте реузультат"); - } - - - @Test - @DisplayName("Тест для проверки непустой невалидной ссылки") - void invalidLink() { - Link_Parser parser = new Link_Parser(); - Assertions.assertNull(parser.parseUrl(invalidLink), "Тест не пройден, проверьте реузультат"); - } - - } diff --git a/FP/migrations/01-schema-1.sql b/FP/migrations/01-schema-1.sql deleted file mode 100644 index 838947b..0000000 --- a/FP/migrations/01-schema-1.sql +++ /dev/null @@ -1,11 +0,0 @@ ---liquibase formatted sql - ---changeset romanova:create-user-table-1 -CREATE TABLE "user" ( - chat_id bigint PRIMARY KEY, - username text UNIQUE NOT NULL, - first_name text, - last_name text -); - ---rollback DROP TABLE "user"; \ No newline at end of file diff --git a/FP/migrations/02-schema-2.sql b/FP/migrations/02-schema-2.sql deleted file mode 100644 index 0e40afb..0000000 --- a/FP/migrations/02-schema-2.sql +++ /dev/null @@ -1,15 +0,0 @@ ---liquibase formatted sql - ---changeset romanova:create-link-table-1 -CREATE TABLE "link" ( - id bigserial PRIMARY KEY, - url text UNIQUE NOT NULL, - checked_at timestamp NOT NULL, - gh_pushed_at timestamp, - gh_description text, - gh_forks_count int, - so_answer_count int, - so_last_edit_date timestamp -); - ---rollback DROP TABLE "link"; \ No newline at end of file diff --git a/FP/migrations/03-schema-3.sql b/FP/migrations/03-schema-3.sql deleted file mode 100644 index c407b73..0000000 --- a/FP/migrations/03-schema-3.sql +++ /dev/null @@ -1,10 +0,0 @@ ---liquibase formatted sql - ---changeset romanova:create-user-link-table-1 -CREATE TABLE "user_link" ( - link_id bigint REFERENCES "link" (id), - chat_id bigint REFERENCES "user" (chat_id), - PRIMARY KEY (link_id,chat_id) -); - ---rollback DROP TABLE "user_link"; \ No newline at end of file diff --git a/FP/migrations/create.sql b/FP/migrations/create.sql deleted file mode 100644 index a4e2a68..0000000 --- a/FP/migrations/create.sql +++ /dev/null @@ -1,18 +0,0 @@ -create table "user" ( - chat_id bigint primary key, - username text unique not null, - first_name text, - last_name text -); - -create table "link" ( - id bigserial primary key, - url text unique not null, - updated_at timestamp not null -); - -create table "user_link" ( - link_id bigint references "link" (id), - chat_id bigint references "user" (chat_id), - primary key (link_id,chat_id) -) \ No newline at end of file diff --git a/FP/migrations/delete.sql b/FP/migrations/delete.sql deleted file mode 100644 index 1fb56bd..0000000 --- a/FP/migrations/delete.sql +++ /dev/null @@ -1,3 +0,0 @@ -drop table "user_link"; -drop table "user"; -drop table "link"; \ No newline at end of file diff --git a/FP/migrations/insert.sql b/FP/migrations/insert.sql deleted file mode 100644 index 30b59be..0000000 --- a/FP/migrations/insert.sql +++ /dev/null @@ -1,37 +0,0 @@ -insert into "user" (chat_id, username, first_name, last_name) -values (42, 'testUser42', 'test', 'testov'), - (34, 'testUser34', 'test', 'testov'), - (65, 'testUser65', 'test', 'testov'), - (45, 'testUser45', 'test', 'testov'), - (523, 'testUser523', 'test', 'testov'), - (645, 'testUser645', 'test', 'testov'), - (7452, 'testUser7452', 'test', 'testov'), - (44562, 'testUser44562', 'test', 'testov'), - (423452, 'testUser423452', 'test', 'testov'), - (2, 'testUser2', 'test', 'testov'); - -insert into "link" (url, updated_at) -values ('https://stackoverflow.com/questions/14141266/postgresql-foreign-key-on-delete-cascade', '2022-05-19 15:13:27'), - ('https://github.com/linus/doctest','2022-01-31 13:13:50'), - ('https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file','2023-03-27 09:58:45'); - -insert into "user_link" (link_id, chat_id) -values (1,42), - (1,45), - (1,2), - (1,7452), - (2,44562), - (2,423452), - (2,645), - (2,523), - (3,34), - (3,65), - (3,7452), - (3,45), - (4,42), - (4,45), - (4,2), - (4,7452); - - - diff --git a/FP/migrations/master.xml b/FP/migrations/master.xml deleted file mode 100644 index c566afc..0000000 --- a/FP/migrations/master.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/FP/pom.xml b/FP/pom.xml index a1baa3d..e38a124 100644 --- a/FP/pom.xml +++ b/FP/pom.xml @@ -1,85 +1,54 @@ - - 4.0.0 - project - project - 0.0.1-SNAPSHOT - pom - - bot - link-parser - scrapper - scrapper-jooq - - - 3.0.1 - 2022.0.0 - 3.10.1 - 23.1.0 - UTF-8 - + + + 4.0.0 - - - - org.springframework.cloud - spring-cloud-dependencies - ${spring-cloud.version} - pom - import - + org.example - - org.springframework.boot - spring-boot-dependencies - ${spring-boot.version} - pom - import - - - org.junit.jupiter - junit-jupiter-params - ${junit.version} - test - - - org.mockito - mockito-core - ${mockito.version} - test - - - org.testcontainers - testcontainers-bom - ${testcontainers.version} - pom - import - - - org.springframework.boot - spring-boot-starter-test - ${spring.test.version} - test - - - + FP + + pom + 1.0 - - - org.jetbrains - annotations - ${annotations.version} - provided - - + + bot + link-parser + scrapper + + + + UTF-8 + 17 + 17 + 3.8.1 + 3.0.1 + 2022.0.0 + 23.1.0 + 5.8.1 + 1.18.0 + + + org.apache.maven.plugins + maven-failsafe-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + false + + org.springframework.boot spring-boot-maven-plugin - ${spring-boot.version} + ${spring-boot.version true @@ -108,16 +77,40 @@ 17 true - - - org.apache.maven.plugins - maven-failsafe-plugin - - - org.apache.maven.plugins - maven-surefire-plugin + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + org.jetbrains + annotations + ${annotations.version} + provided + + + org.testcontainers + testcontainers-bom + ${testcontainers.version} + pom + import + + + \ No newline at end of file diff --git a/FP/scrapper-jooq/.classpath b/FP/scrapper-jooq/.classpath deleted file mode 100644 index ead1d0f..0000000 --- a/FP/scrapper-jooq/.classpath +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/FP/scrapper-jooq/.gitignore b/FP/scrapper-jooq/.gitignore deleted file mode 100644 index b83d222..0000000 --- a/FP/scrapper-jooq/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/FP/scrapper-jooq/.project b/FP/scrapper-jooq/.project deleted file mode 100644 index f320f87..0000000 --- a/FP/scrapper-jooq/.project +++ /dev/null @@ -1,23 +0,0 @@ - - - scrapper-jooq - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - - diff --git a/FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs b/FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index 609d3ca..0000000 --- a/FP/scrapper-jooq/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,4 +0,0 @@ -eclipse.preferences.version=1 -encoding//src/main/resources=UTF-8 -encoding//src/test/resources=UTF-8 -encoding/=UTF-8 diff --git a/FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs b/FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 5e4ec05..0000000 --- a/FP/scrapper-jooq/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,9 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.methodParameters=generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 -org.eclipse.jdt.core.compiler.compliance=17 -org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore -org.eclipse.jdt.core.compiler.release=enabled -org.eclipse.jdt.core.compiler.source=17 diff --git a/FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs b/FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f..0000000 --- a/FP/scrapper-jooq/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/FP/scrapper-jooq/pom.xml b/FP/scrapper-jooq/pom.xml deleted file mode 100644 index b6f0785..0000000 --- a/FP/scrapper-jooq/pom.xml +++ /dev/null @@ -1,40 +0,0 @@ - - 4.0.0 - - project - project - 0.0.1-SNAPSHOT - - scrapper-jooq - - 17 - 17 - UTF-8 - - - - - org.springframework.boot - spring-boot-starter-jooq - - - org.jooq - jooq-codegen - - - org.jooq - jooq-meta-extensions-liquibase - 3.18.3 - - - org.jooq - jooq-postgres-extensions - 3.18.3 - - - org.liquibase - liquibase-core - - - - \ No newline at end of file diff --git a/FP/scrapper-jooq/src/main/java/JooqCodegen.java b/FP/scrapper-jooq/src/main/java/JooqCodegen.java deleted file mode 100644 index ee35d24..0000000 --- a/FP/scrapper-jooq/src/main/java/JooqCodegen.java +++ /dev/null @@ -1,49 +0,0 @@ -import org.jooq.codegen.GenerationTool; -import org.jooq.meta.jaxb.Configuration; -import org.jooq.meta.jaxb.Database; -import org.jooq.meta.jaxb.Generate; -import org.jooq.meta.jaxb.Generator; -import org.jooq.meta.jaxb.Property; -import org.jooq.meta.jaxb.Target; - -public class JooqCodegen { - public static void main(String[] args) throws Exception { - Database database = new Database() - .withName("org.jooq.meta.extensions.liquibase.LiquibaseDatabase") - .withProperties( - new Property().withKey("rootPath").withValue("migrations"), - new Property().withKey("scripts").withValue("master.xml") - ); - - Generate options = new Generate() - .withGeneratedAnnotation(true) - .withGeneratedAnnotationDate(false) - .withNullableAnnotation(true) - .withNullableAnnotationType("org.jetbrains.annotations.Nullable") - .withNonnullAnnotation(true) - .withNonnullAnnotationType("org.jetbrains.annotations.NotNull") - .withJpaAnnotations(false) - .withValidationAnnotations(true) - .withSpringAnnotations(true) - .withConstructorPropertiesAnnotation(true) - .withConstructorPropertiesAnnotationOnPojos(true) - .withConstructorPropertiesAnnotationOnRecords(true) - .withFluentSetters(false) - .withDaos(false) - .withPojos(true); - - Target target = new Target() - .withPackageName("ru.tinkoff.edu.java.scrapper.domain.jooq") - .withDirectory("scrapper/src/main/java"); - - Configuration configuration = new Configuration() - .withGenerator( - new Generator() - .withDatabase(database) - .withGenerate(options) - .withTarget(target) - ); - - GenerationTool.generate(configuration); - } -} \ No newline at end of file diff --git a/FP/scrapper/.classpath b/FP/scrapper/.classpath deleted file mode 100644 index a08fc4f..0000000 --- a/FP/scrapper/.classpath +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/FP/scrapper/.gitignore b/FP/scrapper/.gitignore deleted file mode 100644 index b83d222..0000000 --- a/FP/scrapper/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/FP/scrapper/.project b/FP/scrapper/.project deleted file mode 100644 index d56fd66..0000000 --- a/FP/scrapper/.project +++ /dev/null @@ -1,23 +0,0 @@ - - - scrapper - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - - diff --git a/FP/scrapper/.settings/org.eclipse.core.resources.prefs b/FP/scrapper/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index 29abf99..0000000 --- a/FP/scrapper/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,6 +0,0 @@ -eclipse.preferences.version=1 -encoding//src/main/java=UTF-8 -encoding//src/main/resources=UTF-8 -encoding//src/test/java=UTF-8 -encoding//src/test/resources=UTF-8 -encoding/=UTF-8 diff --git a/FP/scrapper/.settings/org.eclipse.jdt.core.prefs b/FP/scrapper/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 5e4ec05..0000000 --- a/FP/scrapper/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,9 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.methodParameters=generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 -org.eclipse.jdt.core.compiler.compliance=17 -org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore -org.eclipse.jdt.core.compiler.release=enabled -org.eclipse.jdt.core.compiler.source=17 diff --git a/FP/scrapper/.settings/org.eclipse.m2e.core.prefs b/FP/scrapper/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f..0000000 --- a/FP/scrapper/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/FP/scrapper/pom.xml b/FP/scrapper/pom.xml index 1b0c4fa..bbd37fb 100644 --- a/FP/scrapper/pom.xml +++ b/FP/scrapper/pom.xml @@ -2,27 +2,38 @@ - 4.0.0 - project - project - 0.0.1-SNAPSHOT - + org.example + FP + 1.0 + + + 4.0.0 + + scrapper - scrapper + + 3.0.1 + 2.7.6 + + - org.springframework.boot - spring-boot-starter-web + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.0.2 + org.springframework.boot spring-boot-starter-validation + ${starter-validation.version} org.springframework.boot - spring-boot-starter-webflux + spring-boot-starter-web + ${starter-web.version} org.springframework.boot @@ -45,25 +56,32 @@ lombok true + - org.springdoc - springdoc-openapi-starter-webmvc-ui - 2.0.2 + org.example + link-parser + 1.0 + compile + + - ru.tinkoff.edu - link-parser - 1.0-SNAPSHOT + org.springframework.boot + spring-boot-starter-webflux + 3.0.5 + + + + org.example + bot + 1.0 + compile org.testcontainers junit-jupiter test - - org.springframework.boot - spring-boot-starter-test - org.testcontainers postgresql @@ -74,6 +92,7 @@ liquibase-core test + org.springframework.boot spring-boot-starter-jdbc @@ -84,37 +103,14 @@ runtime - org.jooq - jooq - - - org.springframework.boot - spring-boot-starter-data-jpa + org.junit.jupiter + junit-jupiter + test - org.springframework.boot - spring-boot-starter-amqp + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 - - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-failsafe-plugin - - - org.apache.maven.plugins - maven-surefire-plugin - - - \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java index fef7338..959ba70 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java @@ -1,22 +1,21 @@ package ru.tinkoff.edu.java.scrapper; import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import ru.tinkoff.edu.java.scrapper.client.ClientConfiguration; import ru.tinkoff.edu.java.scrapper.configuration.ApplicationConfig; -import org.springframework.scheduling.annotation.EnableScheduling; -import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity; -import ru.tinkoff.edu.java.scrapper.configuration.ApplicationConfig; -import ru.tinkoff.edu.java.scrapper.service.jpa.impl.JpaSubscriptionServiceImpl; -import ru.tinkoff.edu.java.scrapper.service.jpa.impl.JpaTgChatServiceImpl; - @SpringBootApplication @EnableConfigurationProperties(ApplicationConfig.class) -@EnableScheduling +@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) public class ScrapperApplication { - public static void main(String[] args) { + + public static void main(String[] args) { var ctx = SpringApplication.run(ScrapperApplication.class, args); ApplicationConfig config = ctx.getBean(ApplicationConfig.class); - } -} \ No newline at end of file + System.out.println("----------------------------------------------------------------"); + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java deleted file mode 100644 index 2e1aacf..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/advice/AppExceptionHandler.java +++ /dev/null @@ -1,33 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.advice; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestControllerAdvice; -import org.springframework.web.client.HttpClientErrorException; -import ru.tinkoff.edu.java.scrapper.dto.ApiErrorResponse; -import ru.tinkoff.edu.java.scrapper.exception.ChatAlreadyExistException; -import ru.tinkoff.edu.java.scrapper.exception.ChatNotFoundException; -import ru.tinkoff.edu.java.scrapper.exception.LinkIsAlreadyAddedException; -import ru.tinkoff.edu.java.scrapper.exception.LinkNotFoundException; - -import java.util.Arrays; - -@RestControllerAdvice -public class AppExceptionHandler { - - @ExceptionHandler({LinkNotFoundException.class, ChatNotFoundException.class}) - @ResponseStatus(value = HttpStatus.NOT_FOUND) - public ApiErrorResponse handleNotFoundExceptions(RuntimeException exception) { - return new ApiErrorResponse( - "Error", HttpStatus.NOT_FOUND.toString(), exception.getClass().getName(), exception.getMessage(), Arrays.stream(exception.getStackTrace()).map(StackTraceElement::toString).toList().toArray(String[]::new)); - } - - - @ExceptionHandler({ChatAlreadyExistException.class, LinkIsAlreadyAddedException.class}) - @ResponseStatus(value = HttpStatus.BAD_REQUEST) - public ApiErrorResponse handleBadRequestExceptions(RuntimeException exception) { - return new ApiErrorResponse( - "Error", HttpStatus.BAD_REQUEST.toString(), exception.getClass().getName(), exception.getMessage(), Arrays.stream(exception.getStackTrace()).map(StackTraceElement::toString).toList().toArray(String[]::new)); - } -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerLinks.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerLinks.java new file mode 100644 index 0000000..c4ad690 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerLinks.java @@ -0,0 +1,44 @@ +package ru.tinkoff.edu.java.scrapper.api; + +import org.springframework.http.HttpStatus; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import ru.tinkoff.edu.java.scrapper.api.model.*; +import ru.tinkoff.edu.java.scrapper.jdbc.JdbcLinkService; + +import java.util.List; + +@RequestMapping("/links") +@RestController +public class ScrapperControllerLinks { + private final JdbcTemplate jdbcTemplate; + JdbcLinkService linkService = new JdbcLinkService(); + + public ScrapperControllerLinks(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @ResponseStatus(HttpStatus.NO_CONTENT) + @DeleteMapping + public void linksDelete( + @RequestHeader("Tg-Chat-Id") Long tgChatId, + @RequestBody RemoveLinkRequest removeLinkRequest + ) { + linkService.removeLink(jdbcTemplate, removeLinkRequest, tgChatId); + } + + @GetMapping + public List linksGet(@RequestHeader("Tg-Chat-Id") Long tgChatId) { + return linkService.getLinks(jdbcTemplate, tgChatId); + } + + @PostMapping + public void linksPost( + @RequestHeader("Tg-Chat-Id") Long tgChatId, + @RequestBody AddLinkRequest addLinkRequest + ) { + linkService.addLink(jdbcTemplate, addLinkRequest, tgChatId); + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerTg.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerTg.java new file mode 100644 index 0000000..cc96bfb --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerTg.java @@ -0,0 +1,29 @@ +package ru.tinkoff.edu.java.scrapper.api; + +import org.springframework.http.HttpStatus; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.web.bind.annotation.*; +import ru.tinkoff.edu.java.scrapper.jdbc.JdbcChatService; +import ru.tinkoff.edu.java.scrapper.jdbc.JdbcLinkService; + +@RequestMapping("/tg-chat") +@RestController +public class ScrapperControllerTg { + + private final JdbcTemplate jdbcTemplate; + JdbcChatService chatService = new JdbcChatService(); + public ScrapperControllerTg(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @ResponseStatus(HttpStatus.NO_CONTENT) + @DeleteMapping("/{id}") + public void tgChatIdDelete(@PathVariable Long id) { + chatService.removeChat(jdbcTemplate, id); + } + + @PostMapping("/{id}") + public void tgChatIdPost(@PathVariable long id) { + chatService.addChat(jdbcTemplate, id); + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/AddLinkRequest.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/AddLinkRequest.java new file mode 100644 index 0000000..7282291 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/AddLinkRequest.java @@ -0,0 +1,3 @@ +package ru.tinkoff.edu.java.scrapper.api.model; + +public record AddLinkRequest(String link) {} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ChatResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ChatResponse.java new file mode 100644 index 0000000..eb09922 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ChatResponse.java @@ -0,0 +1,3 @@ +package ru.tinkoff.edu.java.scrapper.api.model; + +public record ChatResponse(long chat_id, int id) {} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkChatResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkChatResponse.java new file mode 100644 index 0000000..1f62147 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkChatResponse.java @@ -0,0 +1,3 @@ +package ru.tinkoff.edu.java.scrapper.api.model; + +public record LinkChatResponse(int linkid, int chatid) {} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkResponse.java new file mode 100644 index 0000000..023172d --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkResponse.java @@ -0,0 +1,3 @@ +package ru.tinkoff.edu.java.scrapper.api.model; + +public record LinkResponse(String url, int id) {} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ListLinksResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ListLinksResponse.java new file mode 100644 index 0000000..9c9ed5b --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ListLinksResponse.java @@ -0,0 +1,6 @@ +package ru.tinkoff.edu.java.scrapper.api.model; + +import java.util.*; + +public record ListLinksResponse(List links, int size) {} + diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/RemoveLinkRequest.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/RemoveLinkRequest.java new file mode 100644 index 0000000..3e2a8f0 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/RemoveLinkRequest.java @@ -0,0 +1,3 @@ +package ru.tinkoff.edu.java.scrapper.api.model; + +public record RemoveLinkRequest(String link) {} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/UpdateService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/UpdateService.java new file mode 100644 index 0000000..006d0b0 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/UpdateService.java @@ -0,0 +1,4 @@ +package ru.tinkoff.edu.java.scrapper.api.model; + +public class UpdateService { +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java deleted file mode 100644 index 021e3ec..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/BotClient.java +++ /dev/null @@ -1,38 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.client; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpStatus; -import org.springframework.web.reactive.function.client.WebClient; -import reactor.core.publisher.Mono; -import ru.tinkoff.edu.java.scrapper.dto.LinkUpdate; -import ru.tinkoff.edu.java.scrapper.exception.BotClientException; -import ru.tinkoff.edu.java.scrapper.service.UpdateNotificationService; - -@Slf4j -public class BotClient { - - @Value("${bot.baseurl}") - private String botBaseUrl; - - private final WebClient webClient; - - public BotClient(WebClient webClient) { - this.webClient = webClient; - } - - public BotClient(String botBaseUrl) { - this.webClient = WebClient.create(botBaseUrl); - } - - public void updateLink(LinkUpdate request) { - log.info("Sending update request to Bot"); - webClient.post().uri("/updates").bodyValue(request).exchangeToMono(r -> { - if (r.statusCode().equals(HttpStatus.BAD_REQUEST)) { - throw new BotClientException("Чат с таким ID не зарегистрирован"); - } - return Mono.empty(); - }).block(); - } - -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/ClientConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/ClientConfiguration.java new file mode 100644 index 0000000..ee3e6b1 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/ClientConfiguration.java @@ -0,0 +1,57 @@ +package ru.tinkoff.edu.java.scrapper.client; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.reactive.function.client.WebClient; +import ru.tinkoff.edu.java.linkparser.LinkParser; + +import java.util.Objects; + + +@Configuration +public class ClientConfiguration { + + private final String BASE_GIT_URL = "https://github.com/Ray-Not/JavaGuava"; + private final String BASE_STACK_URL = "https://stackoverflow.com/questions/1642028/what-is-the-operator-in-c"; + @Value("${git.link}") + String gitLink; + @Value("${stack.link}") + String stackLink; + static WebClient.Builder builder = WebClient.builder(); + LinkParser pars = new LinkParser(); + + @Bean + public WeatherRecord weatherClient() { + WeatherRecord weatherResponse = builder.build() + .get() + .uri("http://api.weatherapi.com/v1/current.json?key=3ff5d13401e44f30a14170938230204&q=Russia&aqi=no") + .retrieve() + .bodyToMono(WeatherRecord.class) + .block(); + return weatherResponse; + } + + public GitHubRecord gitHubClient( + String link + ) { + return builder.build() + .get() + .uri("https://api.github.com/repos/" + link) + .retrieve() + .bodyToMono(GitHubRecord.class) + .block(); + } + + public StackOverflowRecord stackOverflowClient( + String link + ) { + String params = "?order=desc&sort=activity&site=stackoverflow"; + return builder.build() + .get() + .uri("https://api.stackexchange.com/2.3/questions/" + link + params) + .retrieve() + .bodyToMono(StackOverflowRecord.class) + .block(); + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java deleted file mode 100644 index 156cf35..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubClient.java +++ /dev/null @@ -1,47 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.client; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.web.reactive.function.client.WebClient; -import ru.tinkoff.edu.java.scrapper.dto.GitHubResponse; -import org.springframework.http.HttpStatus; -import ru.tinkoff.edu.java.scrapper.exception.GitHubRequestException; - -public class GitHubClient { - - - @Value("${gh.baseurl}") - private String gitHubBaseUrl; - - private final WebClient webClient; - - //для использования baseUrl по умолчанию (берётся из properties) - public GitHubClient() { - this.webClient = WebClient.create(gitHubBaseUrl); - } - - - //можно указать базовый URL - public GitHubClient(String baseUrl) { - this.webClient = WebClient.create(baseUrl); - } - - - public GitHubResponse fetchRepo(String owner, String repo) { - GitHubResponse response = webClient.get().uri("/repos/{owner}/{repo}", owner, repo).exchangeToMono(r->{ - if (!r.statusCode().equals(HttpStatus.OK)) throw new GitHubRequestException("Error with request to GH API"); - return r.bodyToMono(GitHubResponse.class); - }).block(); - - return response; - - } - public void strFetchRepo(String owner, String repo){ - String strReponse = webClient.get().uri("/repos/{owner}/{repo}", owner, repo).exchangeToMono(r->{ - if (!r.statusCode().equals(HttpStatus.OK)) throw new GitHubRequestException("Error with request to GH API"); - return r.bodyToMono(String.class); - }).block(); - - System.out.println(strReponse); - - } -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubRecord.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubRecord.java new file mode 100644 index 0000000..97ef980 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/GitHubRecord.java @@ -0,0 +1,19 @@ +package ru.tinkoff.edu.java.scrapper.client; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.time.OffsetDateTime; +import java.util.HashMap; + +public record GitHubRecord( + @JsonProperty("full_name") String name, + @JsonProperty("owner") HashMap owner, + @JsonProperty("private") boolean is_private, + @JsonProperty("node_id") String node_id, + @JsonProperty("html_url") String url, + @JsonProperty("description") String description, + @JsonProperty("created_at") OffsetDateTime createdAt, + @JsonProperty("updated_at") OffsetDateTime updatedAt, + @JsonProperty("pushed_at") OffsetDateTime pushedAt + +) {} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java deleted file mode 100644 index 6651dd9..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowClient.java +++ /dev/null @@ -1,44 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.client; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.web.reactive.function.client.WebClient; -import org.springframework.http.HttpStatus; -import ru.tinkoff.edu.java.scrapper.dto.StackOverflowItem; -import ru.tinkoff.edu.java.scrapper.dto.StackOverflowResponse; -import ru.tinkoff.edu.java.scrapper.exception.BadResponseFromApiException; -import ru.tinkoff.edu.java.scrapper.dto.GitHubResponse; -import ru.tinkoff.edu.java.scrapper.exception.GitHubRequestException; -import ru.tinkoff.edu.java.scrapper.exception.StackOverflowRequestException; - -public class StackOverflowClient { - - @Value("${so.baseurl}") - private String stackOverflowBaseUrl; - - private final WebClient webClient; - - - //для использования baseUrl по умолчанию (берётся из properties) - public StackOverflowClient() { - this.webClient = WebClient.create(stackOverflowBaseUrl); - } - - - //можно указать базовый URL - public StackOverflowClient(String baseUrl) { - this.webClient = WebClient.create(baseUrl); - } - - public StackOverflowItem fetchQuestion(long id) { - - StackOverflowResponse response = webClient.get().uri("/questions/{id}?order=desc&sort=activity&site=stackoverflow", id).exchangeToMono(r->{ - if (!r.statusCode().equals(HttpStatus.OK)) throw new StackOverflowRequestException("Error with request to SO API"); - return r.bodyToMono(StackOverflowResponse.class); - }).block(); - - if (response == null || response.items().size() == 0) - throw new BadResponseFromApiException("API StackOverflow returned bad response"); - - return response.items().get(0); - } -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowRecord.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowRecord.java new file mode 100644 index 0000000..6013400 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/StackOverflowRecord.java @@ -0,0 +1,10 @@ +package ru.tinkoff.edu.java.scrapper.client; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +public record StackOverflowRecord( + @JsonProperty("has_more") boolean has_more, + @JsonProperty("items") List owner +) {} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/WeatherRecord.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/WeatherRecord.java new file mode 100644 index 0000000..5ee9adc --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/client/WeatherRecord.java @@ -0,0 +1,11 @@ +package ru.tinkoff.edu.java.scrapper.client; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.HashMap; +import java.util.List; + +public record WeatherRecord( + @JsonProperty("location") HashMap location, + @JsonProperty("current") HashMap current + ) {} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java index 856e54e..3a82d60 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java @@ -2,25 +2,14 @@ import jakarta.validation.constraints.NotNull; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Bean; +import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.validation.annotation.Validated; import ru.tinkoff.edu.java.scrapper.schedule.Scheduler; @Validated @ConfigurationProperties(prefix = "app", ignoreUnknownFields = false) -public record ApplicationConfig(@NotNull String test, - @NotNull Scheduler scheduler, - @NotNull AccessType dataBaseAccessType, - @NotNull Boolean useQueue, - String queueName, - String exchangeName, - String routingKey){ - - @Bean - public long schedulerIntervalMs(ApplicationConfig config) { - return config.scheduler().interval().toMillis(); - } - public enum AccessType { - JDBC, JPA, JOOQ - } -} \ No newline at end of file +@EnableScheduling +public record ApplicationConfig( + @NotNull String test, + @NotNull Scheduler scheduler +) {} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java deleted file mode 100644 index 8694acf..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ClientConfiguration.java +++ /dev/null @@ -1,44 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.configuration; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import ru.tinkoff.edu.java.scrapper.client.GitHubClient; -import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient; -import org.springframework.web.reactive.function.client.WebClient; -import ru.tinkoff.edu.java.scrapper.client.BotClient; - -@Configuration -public class ClientConfiguration { - - @Value("${gh.baseurl}") - private String gitHubBaseUrl; - - @Value("${so.baseurl}") - private String stackOverflowBaseUrl; - - @Value("${bot.baseurl}") - private String botBaseUrl; - - - //Регистрируем клиентов как бины - @Bean - public GitHubClient gitHubClientService() { - return new GitHubClient(gitHubBaseUrl); - } - - @Bean - public StackOverflowClient stackOverflowClientService() { - return new StackOverflowClient(stackOverflowBaseUrl); - } - @Bean - public WebClient ghWebClient(){ - return WebClient.create(gitHubBaseUrl); - } - - @Bean - public WebClient soWebClient(){ - return WebClient.create(stackOverflowBaseUrl); - } - -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java deleted file mode 100644 index df6780e..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/HTTPConfiguration.java +++ /dev/null @@ -1,28 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.configuration; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.reactive.function.client.WebClient; -import ru.tinkoff.edu.java.scrapper.client.BotClient; - -@Configuration -@ConditionalOnProperty(prefix = "app", name = "use-queue", havingValue = "false") -public class HTTPConfiguration { - - @Value("${bot.baseurl}") - private String botBaseUrl; - - - @Bean - public BotClient botClient(){return new BotClient(botBaseUrl);} - - @Bean - public WebClient botWebClient(){ - return WebClient.create(botBaseUrl); - } - - - -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java deleted file mode 100644 index e400f15..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/LinkParserConfiguration.java +++ /dev/null @@ -1,14 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.configuration; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import ru.tinkoff.edu.java.link_parser.parser.Link_Parser; - -@Configuration -public class LinkParserConfiguration { - - @Bean - public Link_Parser linkParser(){ - return new Link_Parser(); - } -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java index d8b1217..b0d9449 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java @@ -1,15 +1,17 @@ package ru.tinkoff.edu.java.scrapper.configuration; import org.springframework.amqp.core.*; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer; +import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter; import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; import org.springframework.amqp.support.converter.MessageConverter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import ru.tinkoff.edu.java.scrapper.service.ScrapperQueueProducer; +import ru.tinkoff.edu.java.scrapper.rabbitmq.ScrapperQueueProducer; -@Configuration -@ConditionalOnProperty(prefix = "app", name = "use-queue", havingValue = "true") +@SpringBootApplication public class RabbitMQConfiguration { private final ApplicationConfig config; @@ -17,7 +19,6 @@ public class RabbitMQConfiguration { public RabbitMQConfiguration(ApplicationConfig config) { this.config = config; } - @Bean Queue queue() { return QueueBuilder.durable(config.queueName()) @@ -41,10 +42,8 @@ public MessageConverter jsonMessageConverter() { return new Jackson2JsonMessageConverter(); } - @Bean public ScrapperQueueProducer scrapperQueueProducer(AmqpTemplate rabbitTemplate) { return new ScrapperQueueProducer(rabbitTemplate, config); } - -} \ No newline at end of file +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java deleted file mode 100644 index d70f747..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JdbcAccessConfiguration.java +++ /dev/null @@ -1,99 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.configuration.database.acess; - -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.jdbc.core.JdbcTemplate; -import ru.tinkoff.edu.java.link_parser.Link_Parser; -import ru.tinkoff.edu.java.scrapper.client.BotClient; -import ru.tinkoff.edu.java.scrapper.client.GitHubClient; -import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient; -import ru.tinkoff.edu.java.scrapper.mapper.LinkRowMapper; -import ru.tinkoff.edu.java.scrapper.mapper.SubscriptionRowMapper; -import ru.tinkoff.edu.java.scrapper.mapper.UserRowMapper; -import ru.tinkoff.edu.java.scrapper.repository.jdbc.LinkJdbcTemplateRepository; -import ru.tinkoff.edu.java.scrapper.repository.jdbc.SubscriptionJdbcTemplateRepository; -import ru.tinkoff.edu.java.scrapper.repository.jdbc.UserJdbcTemplateRepository; -import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.LinkRepository; -import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository; -import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.UserRepository; -import ru.tinkoff.edu.java.scrapper.service.UpdateNotificationService; -import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService; -import ru.tinkoff.edu.java.scrapper.service.contract.SubscriptionService; -import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService; -import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.LinkUpdateServiceImpl; -import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.SubscriptionServiceImpl; -import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.TgChatServiceImpl; - -@Configuration -@ConditionalOnProperty(prefix = "app", name = "database-access-type", havingValue = "jdbc") -public class JdbcAccessConfiguration { - - @Bean - public LinkRowMapper linkRowMapper() { - return new LinkRowMapper(); - } - - @Bean - public SubscriptionRowMapper subscriptionRowMapper() { - return new SubscriptionRowMapper(); - } - - @Bean - public UserRowMapper userRowMapper() { - return new UserRowMapper(); - } - - @Bean - public LinkRepository linkRepository(JdbcTemplate jdbcTemplate, LinkRowMapper linkRowMapper) { - return new LinkJdbcTemplateRepository(jdbcTemplate, linkRowMapper); - } - - @Bean - public SubscriptionRepository subscriptionRepository(JdbcTemplate jdbcTemplate, SubscriptionRowMapper subscriptionRowMapper) { - return new SubscriptionJdbcTemplateRepository(jdbcTemplate, subscriptionRowMapper, linkRowMapper()); - } - - @Bean - public UserRepository userRepository(JdbcTemplate jdbcTemplate, UserRowMapper userRowMapper) { - return new UserJdbcTemplateRepository(jdbcTemplate, userRowMapper); - } - - @Bean - public LinkUpdateService linkUpdateService( - LinkRepository linkRepository, - SubscriptionRepository subscriptionRepository, - Link_Parser linkParser, - GitHubClient gitHubClient, - StackOverflowClient stackOverflowClient, - BotClient botClient - ) { - return new LinkUpdateServiceImpl( - linkRepository, - subscriptionRepository, - linkParser, - gitHubClient, - stackOverflowClient, - botClient); - } - - @Bean - public SubscriptionService subscriptionService( - LinkRepository linkRepository, - SubscriptionRepository subscriptionRepository - ) { - return new SubscriptionServiceImpl( - linkRepository, - subscriptionRepository); - } - - @Bean - public TgChatService tgChatService( - UserRepository userRepository, - SubscriptionRepository subscriptionRepository - ) { - return new TgChatServiceImpl( - userRepository, - subscriptionRepository); - } -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java deleted file mode 100644 index 47864de..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JooqAccessConfiguration.java +++ /dev/null @@ -1,84 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.configuration.database.acess; - -import org.jooq.DSLContext; -import org.jooq.impl.DSL; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import ru.tinkoff.edu.java.link_parser.Link_Parser; -import ru.tinkoff.edu.java.scrapper.client.BotClient; -import ru.tinkoff.edu.java.scrapper.client.GitHubClient; -import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient; -import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.LinkRepository; -import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository; -import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.UserRepository; -import ru.tinkoff.edu.java.scrapper.repository.jooq.LinkJooqRepository; -import ru.tinkoff.edu.java.scrapper.repository.jooq.SubscriptionJooqRepository; -import ru.tinkoff.edu.java.scrapper.repository.jooq.UserJooqRepository; -import ru.tinkoff.edu.java.scrapper.service.UpdateNotificationService; -import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService; -import ru.tinkoff.edu.java.scrapper.service.contract.SubscriptionService; -import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService; -import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.LinkUpdateServiceImpl; -import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.SubscriptionServiceImpl; -import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.TgChatServiceImpl; -@Configuration -@ConditionalOnProperty(prefix = "app", name = "database-access-type", havingValue = "jooq") -public class JooqAccessConfiguration { - - - @Bean - public LinkRepository linkRepository(DSLContext dslContext){ - return new LinkJooqRepository(dslContext); - } - - @Bean - public SubscriptionRepository subscriptionRepository(DSLContext dslContext){ - return new SubscriptionJooqRepository(dslContext); - } - - - @Bean - public UserRepository userRepository(DSLContext dslContext){ - return new UserJooqRepository(dslContext); - } - - @Bean - public LinkUpdateService linkUpdateService( - LinkRepository linkRepository, - SubscriptionRepository subscriptionRepository, - LinkParser linkParser, - GitHubClient gitHubClient, - StackOverflowClient stackOverflowClient, - BotClient botClient - ) { - return new LinkUpdateServiceImpl( - linkRepository, - subscriptionRepository, - linkParser, - gitHubClient, - stackOverflowClient, - botClient); - } - - @Bean - public SubscriptionService subscriptionService( - LinkRepository linkRepository, - SubscriptionRepository subscriptionRepository - ) { - return new SubscriptionServiceImpl( - linkRepository, - subscriptionRepository); - } - - @Bean - public TgChatService tgChatService( - UserRepository userRepository, - SubscriptionRepository subscriptionRepository - ) { - return new TgChatServiceImpl( - userRepository, - subscriptionRepository); - } - -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java deleted file mode 100644 index ff97aba..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/database/acess/JpaAccessConfiguration.java +++ /dev/null @@ -1,61 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.configuration.database.acess; - -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import ru.tinkoff.edu.java.link_parser.Link_Parser; -import ru.tinkoff.edu.java.scrapper.client.BotClient; -import ru.tinkoff.edu.java.scrapper.client.GitHubClient; -import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient; -import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository; -import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.UserRepository; -import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaLinkRepository; -import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaUserRepository; -import ru.tinkoff.edu.java.scrapper.service.UpdateNotificationService; -import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService; -import ru.tinkoff.edu.java.scrapper.service.contract.SubscriptionService; -import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService; -import ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl.TgChatServiceImpl; -import ru.tinkoff.edu.java.scrapper.service.jpa.impl.JpaLinkUpdateServiceImpl; -import ru.tinkoff.edu.java.scrapper.service.jpa.impl.JpaSubscriptionServiceImpl; -import ru.tinkoff.edu.java.scrapper.service.jpa.impl.JpaTgChatServiceImpl; - -@Configuration -@ConditionalOnProperty(prefix = "app", name = "database-access-type", havingValue = "jpa") -public class JpaAccessConfiguration { - - @Bean - public LinkUpdateService linkUpdateService( - JpaLinkRepository linkRepository, - Link_Parser linkParser, - GitHubClient gitHubClient, - StackOverflowClient stackOverflowClient, - BotClient botClient) { - return new JpaLinkUpdateServiceImpl( - linkRepository, - linkParser, - gitHubClient, - stackOverflowClient, - botClient - ); - } - - @Bean - public SubscriptionService subscriptionService( - JpaLinkRepository linkRepository, - JpaUserRepository userRepository) { - return new JpaSubscriptionServiceImpl( - linkRepository, - userRepository - ); - } - - @Bean - public TgChatService tgChatService( - JpaUserRepository userRepository) { - return new JpaTgChatServiceImpl( - userRepository - ); - } - -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java deleted file mode 100644 index 97985ba..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/AddLinkRequest.java +++ /dev/null @@ -1,5 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.dto; - -public record AddLinkRequest(String link) { - -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java deleted file mode 100644 index 7c065be..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ApiErrorResponse.java +++ /dev/null @@ -1,6 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.dto; - -public record ApiErrorResponse(String description, String code, String exceptionName, - String exceptionMessage, String[] stacktrace) { - -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java deleted file mode 100644 index 8f6367c..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/GitHubResponse.java +++ /dev/null @@ -1,25 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.dto; - -import com.fasterxml.jackson.annotation.JsonProperty; -import java.time.OffsetDateTime; - -public record GitHubResponse(@JsonProperty("pushed") OffsetDateTime pushedAt, - @JsonProperty("updated") OffsetDateTime updatedAt, - @JsonProperty("full_name") String fullName, - @JsonProperty("description") String description, - @JsonProperty("forks_count") int forksCount -) { - - -@Override -public String toString() { - return "GitHubResponse{" + - "pushedAt=" + pushedAt + - ", updatedAt=" + updatedAt + - ", fullName='" + fullName + '\'' + - ", description='" + description + '\'' + - ", forksCount=" + forksCount + - '}'; -} - -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java deleted file mode 100644 index cadc95f..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkResponse.java +++ /dev/null @@ -1,5 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.dto; - -public record LinkResponse(long id, String url) { - -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java deleted file mode 100644 index 1b6410a..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/LinkUpdate.java +++ /dev/null @@ -1,5 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.dto; - -public record LinkUpdate(Long id, String url, String description, Long[] tgChatIds) { - -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java deleted file mode 100644 index a142f3a..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/ListLinkResponse.java +++ /dev/null @@ -1,8 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.dto; - -import ru.tinkoff.edu.java.scrapper.model.Link; -import java.util.List; - -public record ListLinkResponse(List links, int size) { - -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java deleted file mode 100644 index 09a3867..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/RemoveLinkRequest.java +++ /dev/null @@ -1,5 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.dto; - -public record RemoveLinkRequest(String link) { - -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java deleted file mode 100644 index 9e2f0b9..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowItem.java +++ /dev/null @@ -1,8 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.dto; -import com.fasterxml.jackson.annotation.JsonProperty; - -import java.time.OffsetDateTime; -public record StackOverflowItem(@JsonProperty("last_edit_date") OffsetDateTime lastActivityDate, - @JsonProperty("last_activity_date") OffsetDateTime lastEditDate) { - -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java deleted file mode 100644 index 50227fc..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/StackOverflowResponse.java +++ /dev/null @@ -1,8 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.dto; -import com.fasterxml.jackson.annotation.JsonProperty; - -import java.time.OffsetDateTime; -import java.util.List; -public record StackOverflowResponse(List items) { - -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java deleted file mode 100644 index 58d769c..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/dto/UserAddDto.java +++ /dev/null @@ -1,8 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.dto; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public record UserAddDto(@JsonProperty("username") String username, - @JsonProperty("first_name") String firstName, - @JsonProperty("last_name") String lastName) { -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java deleted file mode 100644 index d5be7a4..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BadResponseFromApiException.java +++ /dev/null @@ -1,12 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.exception; - -public class BadResponseFromApiException extends RuntimeException { - - public BadResponseFromApiException() { - } - - public BadResponseFromApiException(String message) { - super(message); - } - -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java deleted file mode 100644 index 9ee4d12..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/BotClientException.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.exception; - -public class BotClientException extends RuntimeException{ - - public BotClientException() { - } - - public BotClientException(String message) { - super(message); - } -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java deleted file mode 100644 index 5dd1124..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatAlreadyExistException.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.exception; - -public class ChatAlreadyExistException extends RuntimeException { - - public ChatAlreadyExistException() { - } - - public ChatAlreadyExistException(String message) { - super(message); - } -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java deleted file mode 100644 index 29dc8cf..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/ChatNotFoundException.java +++ /dev/null @@ -1,12 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.exception; - -public class ChatNotFoundException extends RuntimeException { - - public ChatNotFoundException(String message) { - super(message); - } - - public ChatNotFoundException() { - } - -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java deleted file mode 100644 index 9bf30c3..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/GitHubRequestException.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.exception; - -public class GitHubRequestException extends RuntimeException{ - - public GitHubRequestException() { - } - - public GitHubRequestException(String message) { - super(message); - } -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java deleted file mode 100644 index 58a7dfb..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkIsAlreadyAddedException.java +++ /dev/null @@ -1,12 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.exception; - -public class LinkIsAlreadyAddedException extends RuntimeException { - - - public LinkIsAlreadyAddedException(String message) { - super(message); - } - - public LinkIsAlreadyAddedException() { - } -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java deleted file mode 100644 index e5c5c62..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/LinkNotFoundException.java +++ /dev/null @@ -1,12 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.exception; - -public class LinkNotFoundException extends RuntimeException { - - public LinkNotFoundException() { - } - - public LinkNotFoundException(String message) { - super(message); - } - -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java deleted file mode 100644 index e714110..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exception/StackOverflowRequestException.java +++ /dev/null @@ -1,12 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.exception; - -public class StackOverflowRequestException extends RuntimeException{ - - public StackOverflowRequestException() { - super(); - } - - public StackOverflowRequestException(String message) { - super(message); - } -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/ScrapperExceptionHandler.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/ScrapperExceptionHandler.java new file mode 100644 index 0000000..55fc0c9 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/ScrapperExceptionHandler.java @@ -0,0 +1,78 @@ +package ru.tinkoff.edu.java.scrapper.exceptions; + +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.MissingRequestHeaderException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; +import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.EntryExsistException; +import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.EntryNotExsistException; +import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.NullLinkException; +import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.UnauthorizationException; +import ru.tinkoff.edu.java.scrapper.exceptions.model.ApiErrorResponse; + +@RestControllerAdvice +public class ScrapperExceptionHandler { + + private ApiErrorResponse setException(Exception exception) { + String[] parsing_class = exception.getClass().toString().split("\\."); + String class_name = parsing_class[parsing_class.length - 1]; + ApiErrorResponse errorObj = new ApiErrorResponse( + exception.getMessage(), + class_name, + exception.toString() + ); + return errorObj; + } + + @ExceptionHandler(HttpMessageNotReadableException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ApiErrorResponse MessageNotReadable(HttpMessageNotReadableException e) { + return setException(e); + } + + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ApiErrorResponse MethodNotSupported(HttpRequestMethodNotSupportedException e) { + return setException(e); + } + + @ExceptionHandler(MissingRequestHeaderException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ApiErrorResponse MissingRequestHeader(MissingRequestHeaderException e) { + return setException(e); + } + + @ExceptionHandler(MethodArgumentTypeMismatchException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ApiErrorResponse ArgumentTypeMismatch(MethodArgumentTypeMismatchException e) { + return setException(e); + } + + @ExceptionHandler(NullLinkException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ApiErrorResponse NullLink(NullLinkException e) { + return setException(e); + } + + @ExceptionHandler(UnauthorizationException.class) + @ResponseStatus(HttpStatus.UNAUTHORIZED) + public ApiErrorResponse Unauthorization(UnauthorizationException e) { + return setException(e); + } + + @ExceptionHandler(EntryExsistException.class) + @ResponseStatus(HttpStatus.FOUND) + public ApiErrorResponse EntryExsist(EntryExsistException e) { + return setException(e); + } + + @ExceptionHandler(EntryNotExsistException.class) + @ResponseStatus(HttpStatus.NOT_FOUND) + public ApiErrorResponse EntryNotExsist(EntryNotExsistException e) { + return setException(e); + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/EntryExsistException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/EntryExsistException.java new file mode 100644 index 0000000..fca436d --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/EntryExsistException.java @@ -0,0 +1,12 @@ +package ru.tinkoff.edu.java.scrapper.exceptions.customExceptions; + +public class EntryExsistException extends RuntimeException { + + public EntryExsistException() { + super(); + } + + public EntryExsistException(String s) { + super(s); + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/EntryNotExsistException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/EntryNotExsistException.java new file mode 100644 index 0000000..e25ba25 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/EntryNotExsistException.java @@ -0,0 +1,12 @@ +package ru.tinkoff.edu.java.scrapper.exceptions.customExceptions; + +public class EntryNotExsistException extends RuntimeException { + + public EntryNotExsistException() { + super(); + } + + public EntryNotExsistException(String s) { + super(s); + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/NullDBException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/NullDBException.java new file mode 100644 index 0000000..cd7baa2 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/NullDBException.java @@ -0,0 +1,12 @@ +package ru.tinkoff.edu.java.scrapper.exceptions.customExceptions; + +public class NullDBException extends RuntimeException { + + public NullDBException() { + super(); + } + + public NullDBException(String s) { + super(s); + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/NullLinkException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/NullLinkException.java new file mode 100644 index 0000000..00ddf4e --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/NullLinkException.java @@ -0,0 +1,12 @@ +package ru.tinkoff.edu.java.scrapper.exceptions.customExceptions; + +public class NullLinkException extends RuntimeException { + + public NullLinkException() { + super(); + } + + public NullLinkException(String s) { + super(s); + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/UnauthorizationException.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/UnauthorizationException.java new file mode 100644 index 0000000..2135ddc --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/customExceptions/UnauthorizationException.java @@ -0,0 +1,12 @@ +package ru.tinkoff.edu.java.scrapper.exceptions.customExceptions; + +public class UnauthorizationException extends RuntimeException { + + public UnauthorizationException() { + super(); + } + + public UnauthorizationException(String s) { + super(s); + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/model/ApiErrorResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/model/ApiErrorResponse.java new file mode 100644 index 0000000..0a8994e --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/exceptions/model/ApiErrorResponse.java @@ -0,0 +1,7 @@ +package ru.tinkoff.edu.java.scrapper.exceptions.model; + +public record ApiErrorResponse( + String exceptionMessage, + String description, + String exceptionName +) {} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcChatService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcChatService.java new file mode 100644 index 0000000..c8757c8 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcChatService.java @@ -0,0 +1,26 @@ +package ru.tinkoff.edu.java.scrapper.jdbc; + +import org.springframework.jdbc.core.JdbcTemplate; +import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.*; +import ru.tinkoff.edu.java.scrapper.jdbc.operations.ChatOperations; +import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkChatOperations; +import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkOperations; + +public class JdbcChatService implements LinkOperations, ChatOperations, LinkChatOperations { + public void addChat(JdbcTemplate jdbc, long chat) { + int chat_id = i_findChat(jdbc, chat); + if (chat_id != 0) { + throw new EntryExsistException("Вы уже зарегистрированы"); + } else { + i_addChat(jdbc, chat); + } + } + + public void removeChat(JdbcTemplate jdbc, long chat) { + int chat_id = i_findChat(jdbc, chat); + if (chat_id != 0) { + i_removeChat(jdbc, chat); + i_removeLinkChatAllChat(jdbc, chat_id); + } else throw new EntryNotExsistException("Пользователь не найден"); + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java new file mode 100644 index 0000000..6eb52b5 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java @@ -0,0 +1,75 @@ +package ru.tinkoff.edu.java.scrapper.jdbc; + +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.web.reactive.function.client.WebClientResponseException; +import ru.tinkoff.edu.java.linkparser.LinkParser; +import ru.tinkoff.edu.java.scrapper.api.model.AddLinkRequest; +import ru.tinkoff.edu.java.scrapper.api.model.LinkResponse; +import ru.tinkoff.edu.java.scrapper.api.model.RemoveLinkRequest; +import ru.tinkoff.edu.java.scrapper.client.ClientConfiguration; +import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.*; +import ru.tinkoff.edu.java.scrapper.jdbc.operations.ChatOperations; +import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkChatOperations; +import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkOperations; + +import java.util.ArrayList; +import java.util.List; + +public class JdbcLinkService implements LinkOperations, ChatOperations, LinkChatOperations { + public void addLink(JdbcTemplate jdbc, AddLinkRequest link, Long chat) { + ClientConfiguration client = new ClientConfiguration(); + LinkParser parser = new LinkParser(); + if (parser.getLink(link.link()) == null) { + throw new NullLinkException("Ссылка невалидна"); + } + try { + client.gitHubClient(parser.getLink(link.link())); + } catch (WebClientResponseException e) { + try { + client.stackOverflowClient(parser.getLink(link.link())); + } catch (WebClientResponseException ex) { + throw new NullLinkException("Ссылка не поддерживается, доступны: Git, StackOverFlow"); + } + } + int link_id = i_findLink(jdbc, link.link()); + int chat_id = i_findChat(jdbc, chat); + if (chat_id == 0) { + throw new UnauthorizationException("Перед использованием нужно зарегистрироваться"); + } + if (link_id == 0) { + i_addLink(jdbc, link); + link_id = i_findLink(jdbc, link.link()); + } + if (i_findLinkChat(jdbc, link_id, chat_id)) { + addLinkChat(jdbc, link_id, chat_id); + }else throw new EntryExsistException("Ссылка уже добавлена!"); + } + + public void removeLink(JdbcTemplate jdbc, RemoveLinkRequest link, long chat) { + int link_id = i_findLink(jdbc, link.link()); + int chat_id = i_findChat(jdbc, chat); + if (chat_id == 0) { + throw new UnauthorizationException("Перед использованием нужно зарегистрироваться"); + } + if (link_id != 0) { + i_removeLink(jdbc, link); + } else throw new EntryNotExsistException("Ссылки не существует"); + if (!i_findLinkChat(jdbc, link_id, chat_id)) { + i_removeLinkChat(jdbc, link_id, chat_id); + } + } + + public List getLinks(JdbcTemplate jdbc, long chat) { + int i; + int chat_id = i_findChat(jdbc, chat); + if (chat_id == 0) { + throw new UnauthorizationException("Перед использованием нужно зарегистрироваться"); + } + ArrayList link_list = new ArrayList<>(); + for (i = 0; i < i_get_all_links_for_chat(jdbc, chat_id).size(); i++){ + link_list.add(i_get_all_links_for_chat(jdbc, chat_id).get(i).linkid()); + } + return i_findAllLink(jdbc, link_list); + } + +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/config/jdbcBean.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/config/jdbcBean.java new file mode 100644 index 0000000..8db6ed9 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/config/jdbcBean.java @@ -0,0 +1,25 @@ +package ru.tinkoff.edu.java.scrapper.jdbc.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.DriverManagerDataSource; + +import javax.sql.DataSource; +@Configuration +public class jdbcBean { + @Bean + public DataSource dataSource() { + DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName("org.postgresql.Driver"); + dataSource.setUrl("jdbc:postgresql://localhost:5432/scrapper"); + dataSource.setUsername("scrap_user"); + dataSource.setPassword("hard_password"); + + return dataSource; + } + @Bean + public JdbcTemplate jdbcTemplate () { + return new JdbcTemplate (dataSource()); + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/ChatMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/ChatMapper.java new file mode 100644 index 0000000..b979f13 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/ChatMapper.java @@ -0,0 +1,14 @@ +package ru.tinkoff.edu.java.scrapper.jdbc.mappers; + +import org.springframework.jdbc.core.RowMapper; +import ru.tinkoff.edu.java.scrapper.api.model.ChatResponse; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class ChatMapper implements RowMapper { + @Override + public ChatResponse mapRow(ResultSet rs, int rowNum) throws SQLException { + return new ChatResponse(rs.getLong("tg_chat_id"), rs.getInt("id")); + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkChatMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkChatMapper.java new file mode 100644 index 0000000..e9e98e7 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkChatMapper.java @@ -0,0 +1,14 @@ +package ru.tinkoff.edu.java.scrapper.jdbc.mappers; + +import org.springframework.jdbc.core.RowMapper; +import ru.tinkoff.edu.java.scrapper.api.model.LinkChatResponse; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class LinkChatMapper implements RowMapper { + @Override + public LinkChatResponse mapRow(ResultSet rs, int rowNum) throws SQLException { + return new LinkChatResponse(rs.getInt("linkid"), rs.getInt("chatid")); + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkMapper.java new file mode 100644 index 0000000..ac50329 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkMapper.java @@ -0,0 +1,15 @@ +package ru.tinkoff.edu.java.scrapper.jdbc.mappers; + + +import org.springframework.jdbc.core.RowMapper; +import ru.tinkoff.edu.java.scrapper.api.model.LinkResponse; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class LinkMapper implements RowMapper { + @Override + public LinkResponse mapRow(ResultSet rs, int rowNum) throws SQLException { + return new LinkResponse(rs.getString("link"), rs.getInt("id")); + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/ChatOperations.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/ChatOperations.java new file mode 100644 index 0000000..3c36c88 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/ChatOperations.java @@ -0,0 +1,50 @@ +package ru.tinkoff.edu.java.scrapper.jdbc.operations; + +import org.springframework.jdbc.core.JdbcTemplate; +import ru.tinkoff.edu.java.scrapper.jdbc.mappers.ChatMapper; +import ru.tinkoff.edu.java.scrapper.jdbc.mappers.LinkMapper; + +public interface ChatOperations { + default void i_addChat( + JdbcTemplate jdbcTemplate, + long chat + ) { + int chat_id; + + try { + chat_id = jdbcTemplate.query( + "SELECT * FROM tgchats WHERE id=(SELECT MAX(id) FROM tgchats)", + new ChatMapper() + ).get(0).id() + 1; + } catch (IndexOutOfBoundsException e) { + chat_id = 1; + } + + jdbcTemplate.update("INSERT INTO tgchats VALUES(?, ?)", chat_id, chat); + } + + default void i_removeChat( + JdbcTemplate jdbcTemplate, + long chat + ){ + String query = "DELETE FROM tgchats WHERE tg_chat_id=(%d)"; + query = query.formatted(chat); + jdbcTemplate.update(query); + } + + default int i_findChat( + JdbcTemplate jdbcTemplate, + long chat + ){ + try { + String query = "SELECT * FROM tgchats WHERE tg_chat_id=(%d)"; + query = query.formatted(chat); + return jdbcTemplate.query( + query, + new ChatMapper() + ).get(0).id(); + } catch (IndexOutOfBoundsException e) { // Если значение не нашлось + return 0; + } + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkChatOperations.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkChatOperations.java new file mode 100644 index 0000000..29cfe7d --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkChatOperations.java @@ -0,0 +1,61 @@ +package ru.tinkoff.edu.java.scrapper.jdbc.operations; + +import org.springframework.jdbc.core.JdbcTemplate; +import ru.tinkoff.edu.java.scrapper.api.model.LinkChatResponse; +import ru.tinkoff.edu.java.scrapper.jdbc.mappers.LinkChatMapper; + +import java.util.List; + +public interface LinkChatOperations { + default void addLinkChat( + JdbcTemplate jdbcTemplate, + int link_id, + int chat_id + ) { + jdbcTemplate.update("INSERT INTO links_tgchats VALUES(?, ?)", link_id, chat_id); + } + + default void i_removeLinkChat( + JdbcTemplate jdbcTemplate, + int link_id, + int chat_id + ) { + String query = "DELETE FROM links_tgchats WHERE linkid=(%d) AND chatid=(%d)"; + query = query.formatted(link_id, chat_id); + jdbcTemplate.update(query); + } + + default void i_removeLinkChatAllChat( + JdbcTemplate jdbcTemplate, + int chat_id + ) { + String query = "DELETE FROM links_tgchats WHERE chatid=(%d)"; + query = query.formatted(chat_id); + jdbcTemplate.update(query); + } + + default boolean i_findLinkChat( + JdbcTemplate jdbcTemplate, + int link_id, + int chat_id + ){ + try { + String query = "SELECT * FROM links_tgchats WHERE linkid=(%d) AND chatid=(%d)"; + query = query.formatted(link_id, chat_id); + jdbcTemplate.query(query, new LinkChatMapper()).get(0); + } catch (IndexOutOfBoundsException e) { // Если значение не нашлось + return true; + } + return false; + } + + default List i_get_all_links_for_chat(JdbcTemplate jdbcTemplate, int chat_id) { + try { + String query = "SELECT * FROM links_tgchats WHERE chatid=(%d)"; + query = query.formatted(chat_id); + return jdbcTemplate.query(query, new LinkChatMapper()); + } catch (IndexOutOfBoundsException e) { // Если значение не нашлось + return null; + } + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java new file mode 100644 index 0000000..ad282fe --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java @@ -0,0 +1,83 @@ +package ru.tinkoff.edu.java.scrapper.jdbc.operations; + +import org.springframework.jdbc.core.JdbcTemplate; +import ru.tinkoff.edu.java.scrapper.api.model.AddLinkRequest; +import ru.tinkoff.edu.java.scrapper.api.model.LinkResponse; +import ru.tinkoff.edu.java.scrapper.api.model.RemoveLinkRequest; +import ru.tinkoff.edu.java.scrapper.jdbc.mappers.LinkMapper; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public interface LinkOperations { + default void i_addLink( + JdbcTemplate jdbcTemplate, + AddLinkRequest addLinkRequest + ) { + int link_id; + + try { + link_id = jdbcTemplate.query( + "SELECT * FROM links WHERE id=(SELECT MAX(id) FROM links)", + new LinkMapper() + ).get(0).id() + 1; + } catch (IndexOutOfBoundsException e) { + link_id = 1; + } + + jdbcTemplate.update("INSERT INTO links VALUES(?, ?)", link_id, addLinkRequest.link()); + } + + default void i_removeLink( + JdbcTemplate jdbcTemplate, + RemoveLinkRequest removeLinkRequest + ){ + String query = "DELETE FROM links where link IN ('%s')"; + query = query.formatted(removeLinkRequest.link()); + jdbcTemplate.update(query); + } + + default List i_findAllLink( + JdbcTemplate jdbcTemplate, + ArrayList links_ids + ){ + try { + String ids = Arrays.toString(links_ids.toArray()); + ids = ids.substring(1, ids.length() - 1); + String query = "SELECT * FROM links WHERE id IN (%s)"; + query = query.formatted(ids); + return jdbcTemplate.query( + query, + new LinkMapper() + ); + } catch (IndexOutOfBoundsException e) { // Если значение не нашлось + return null; + } + } + + default int i_findLink( + JdbcTemplate jdbcTemplate, + String link + ){ + try { + String query = "SELECT * FROM links WHERE link IN ('%s')"; + query = query.formatted(link); + return jdbcTemplate.query( + query, + new LinkMapper() + ).get(0).id(); + } catch (IndexOutOfBoundsException e) { // Если значение не нашлось + return 0; + } + } + + default List i_getAllIds(JdbcTemplate jdbcTemplate) { + try { + String query = "SELECT * FROM links"; + return jdbcTemplate.query(query, new LinkMapper()); + } catch (IndexOutOfBoundsException e) { // Если значение не нашлось + return null; + } + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java deleted file mode 100644 index 72df1e2..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/LinkRowMapper.java +++ /dev/null @@ -1,27 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.mapper; - -import org.springframework.jdbc.core.RowMapper; -import org.springframework.stereotype.Component; -import ru.tinkoff.edu.java.scrapper.model.Link; -import ru.tinkoff.edu.java.scrapper.model.User; - -import java.sql.ResultSet; -import java.sql.SQLException; - -@Component -public class LinkRowMapper implements RowMapper { - - @Override - public Link mapRow(ResultSet rs, int rowNum) throws SQLException { - Link link = new Link(); - link.setId(rs.getLong("id")); - link.setUrl(rs.getString("url")); - link.setCheckedAt(rs.getTimestamp("checked_at")); - link.setGhPushedAt(rs.getTimestamp("gh_pushed_at")); - link.setGhDescription(rs.getString("gh_description")); - link.setGhForksCount(rs.getInt("gh_forks_count")); - link.setSoAnswerCount(rs.getInt("so_answer_count")); - link.setSoLastEditDate(rs.getTimestamp("so_last_edit_date")); - return link; - } -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java deleted file mode 100644 index bd76b2b..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/SubscriptionRowMapper.java +++ /dev/null @@ -1,20 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.mapper; - -import org.springframework.jdbc.core.RowMapper; -import org.springframework.stereotype.Component; -import ru.tinkoff.edu.java.scrapper.model.Relation; -import java.sql.ResultSet; -import java.sql.SQLException; - -@Component -public class SubscriptionRowMapper implements RowMapper { - - @Override - public Relation mapRow(ResultSet rs, int rowNum) throws SQLException { - Relation relation = new Relation(); - relation.setLinkId(rs.getLong("link_id")); - relation.setChatId(rs.getLong("chat_id")); - - return relation; - } -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java deleted file mode 100644 index 4597040..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/mapper/UserRowMapper.java +++ /dev/null @@ -1,24 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.mapper; - -import org.springframework.jdbc.core.RowMapper; -import org.springframework.stereotype.Component; -import ru.tinkoff.edu.java.scrapper.model.User; - -import java.sql.ResultSet; -import java.sql.SQLException; - - -@Component -public class UserRowMapper implements RowMapper { - - - @Override - public User mapRow(ResultSet rs, int rowNum) throws SQLException { - User user = new User(); - user.setChatId(rs.getLong("chat_id")); - user.setUsername(rs.getString("username")); - user.setFirstName(rs.getString("first_name")); - user.setLastName(rs.getString("last_name")); - return user; - } -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java deleted file mode 100644 index 59b4a92..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/Link.java +++ /dev/null @@ -1,31 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.model.commonDto; - -import lombok.Data; -import java.sql.Timestamp; -import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity; - -@Data -public class Link { - - - private Long id; - private String url; - private Timestamp checkedAt; - private Timestamp ghPushedAt; - private String ghDescription; - private int ghForksCount; - private Timestamp soLastEditDate; - private int soAnswerCount; - public static Link fromEntity(LinkEntity linkEntity){ - Link link = new Link(); - link.setId(linkEntity.getId()); - link.setUrl(linkEntity.getUrl()); - link.setCheckedAt(linkEntity.getCheckedAt()); - link.setGhDescription(linkEntity.getGhDescription()); - link.setGhPushedAt(linkEntity.getGhPushedAt()); - Integer forks = linkEntity.getGhForksCount(); if (forks == null) link.setGhForksCount(0); else link.setGhForksCount(forks); - Integer answers = linkEntity.getSoAnswerCount(); if (answers == null) link.setSoAnswerCount(0); else link.setSoAnswerCount(answers); - link.setSoLastEditDate(linkEntity.getSoLastEditDate()); - return link; - } -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java deleted file mode 100644 index 74f7693..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/commonDto/User.java +++ /dev/null @@ -1,32 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.model.commonDto; - -import lombok.Data; -import lombok.NoArgsConstructor; -import ru.tinkoff.edu.java.scrapper.model.jpa.UserEntity; - -@Data -@NoArgsConstructor -public class User { - - public User(Long chatId, String username, String firstName, String lastName) { - this.chatId = chatId; - this.username = username; - this.firstName = firstName; - this.lastName = lastName; - } - - private Long chatId; - private String username; - private String firstName; - private String lastName; - public static UserEntity toEntity(User user){ - UserEntity userEntity = new UserEntity(); - - userEntity.setChatId(user.getChatId()); - userEntity.setUsername(user.getUsername()); - userEntity.setFirstName(user.getFirstName()); - userEntity.setLastName(user.getLastName()); - - return userEntity; - } -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java deleted file mode 100644 index abe684a..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jdbcAndJooq/Relation.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.model.jdbcAndJooq; - -import lombok.Data; - -@Data -public class Relation { - - private Long linkId; - private Long chatId; - -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java deleted file mode 100644 index bd4469b..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/LinkEntity.java +++ /dev/null @@ -1,40 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.model.jpa; - -import jakarta.persistence.*; -import lombok.Data; -import java.sql.Timestamp; -import java.util.List; - -@Entity -@Table(name = "link") -@Data -public class LinkEntity { - - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "url", unique = true, nullable = false) - private String url; - - @Column(name = "checked_at", nullable = false) - private Timestamp checkedAt; - - @Column(name = "gh_pushed_at") - private Timestamp ghPushedAt; - - @Column(name = "gh_description") - private String ghDescription; - - @Column(name = "gh_forks_count") - private Integer ghForksCount; - - @Column(name = "so_last_edit_date") - private Timestamp soLastEditDate; - - @Column(name = "so_answer_count") - private Integer soAnswerCount; - - -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java deleted file mode 100644 index 8f49d40..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/jpa/UserEntity.java +++ /dev/null @@ -1,30 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.model.jpa; - -import jakarta.persistence.*; -import lombok.Data; -import java.util.List; - -@Entity -@Table(name = "\"user\"") -@Data -public class UserEntity { - - @Id - @Column(name = "chat_id") - private Long chatId; - - @Column(name = "username", unique = true, nullable = false) - private String username; - - @Column(name = "first_name") - private String firstName; - - @Column(name = "last_name") - private String lastName; - - @ManyToMany(fetch = FetchType.LAZY) - @JoinTable(name = "user_link", - joinColumns = @JoinColumn(name = "chat_id"), - inverseJoinColumns = @JoinColumn(name = "link_id")) - private List links; -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java similarity index 95% rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java rename to FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java index cf4a7ae..3507568 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/service/ScrapperQueueListener.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java @@ -1,5 +1,3 @@ -package ru.tinkoff.edu.java.bot.service; - import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.core.AmqpTemplate; import org.springframework.amqp.rabbit.annotation.RabbitHandler; @@ -29,4 +27,4 @@ public void receiver(LinkUpdate update) { } -} +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java similarity index 50% rename from FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java rename to FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java index 91471de..84baa14 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/ScrapperQueueProducer.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java @@ -1,13 +1,14 @@ -package ru.tinkoff.edu.java.scrapper.service; +package ru.tinkoff.edu.java.scrapper.rabbitmq; -import lombok.extern.slf4j.Slf4j; +import lombok.RequiredArgsConstructor; import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.stereotype.Service; +import ru.tinkoff.edu.java.bot.api.model.LinkUpdate; + import ru.tinkoff.edu.java.scrapper.configuration.ApplicationConfig; -import ru.tinkoff.edu.java.scrapper.dto.LinkUpdate; -@Slf4j -//бин регистрируется в конфиге, т.к. его не нужно инициализировать в случае общения по HTTP -public class ScrapperQueueProducer implements UpdateNotificationService { +@Service +public class ScrapperQueueProducer { private final AmqpTemplate rabbitTemplate; @@ -19,8 +20,8 @@ public ScrapperQueueProducer(AmqpTemplate rabbitTemplate, ApplicationConfig conf this.config = config; } - public void updateLink(LinkUpdate update) { + public void send(LinkUpdate update) { rabbitTemplate.convertAndSend(config.exchangeName(), config.routingKey(), update); - log.info("UpdateMessage " + update + " has been sent"); + System.out.println("Mess update: " + update); } -} \ No newline at end of file +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java deleted file mode 100644 index 38d0931..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/LinkJdbcTemplateRepository.java +++ /dev/null @@ -1,86 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.repository.jdbc; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.stereotype.Repository; -import ru.tinkoff.edu.java.scrapper.mapper.LinkRowMapper; -import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; -import ru.tinkoff.edu.java.scrapper.repository.LinkRepository; - -import java.sql.Timestamp; -import java.util.List; - -@Slf4j -public class LinkJdbcTemplateRepository implements LinkRepository { - - - private final JdbcTemplate jdbcTemplate; - - private final LinkRowMapper linkRowMapper; - - public LinkJdbcTemplateRepository(JdbcTemplate jdbcTemplate, LinkRowMapper linkRowMapper) { - this.jdbcTemplate = jdbcTemplate; - this.linkRowMapper = linkRowMapper; - } - - - @Override - public List findAll() { - log.info("findAll() method invocation in linkRepo"); - String sql = "select * from link"; - return jdbcTemplate.query(sql, linkRowMapper); - } - - @Override - public Link findByUrl(String url) { - log.info("findByUrl() method invocation in linkRepo"); - String sql = "select * from link where link.url = ?"; - List link = jdbcTemplate.query(sql, linkRowMapper, url); - return link.size() == 0 ? null : link.get(0); - } - - @Override - public void add(Link link) { - log.info("add() method invocation in linkRepo"); - String sql = "insert into link (url, updated_at) values(?, ?)"; - jdbcTemplate.update(sql, link.getUrl(), link.getUpdatedAt()); - } - - - @Override - public void updateDate(Link link) { - log.info("updateDate() method invocation in linkRepo"); - String sql = "update link set updated_at = ? where id = ?"; - jdbcTemplate.update(sql, link.getUpdatedAt(), link.getId()); - } - - @Override - public void remove(Long id) { - log.info("remove() method invocation in linkRepo"); - String sql = "delete from link where link.id = ?"; - jdbcTemplate.update(sql, id); - } - - @Override - //поиск ссылок по критерию - public List findOldLinks(Long timeUpdateDelta) { - log.info("findOldLinks() method invocation in linkRepo"); - Timestamp compareDate = new Timestamp(System.currentTimeMillis() - timeUpdateDelta*1000); - String sql = "select * from link where link.updated_at < ? order by link.updated_at desc"; - return jdbcTemplate.query(sql,linkRowMapper,compareDate); - } - @Override - public void updateGhLink(Link link) { - log.info("updateGhLink() method invocation in linkJdbcRepo"); - String sql = "update link set gh_forks_count = ?, gh_description = ?, gh_pushed_at = ? where id = ?"; - jdbcTemplate.update(sql, link.getGhForksCount(), link.getGhDescription(), link.getGhPushedAt(), link.getId()); - } - - @Override - public void updateSoLink(Link link) { - log.info("updateSoLastEditDate() method invocation in linkJdbcRepo"); - String sql = "update link set so_last_edit_date = ?, so_answer_count = ? where id = ?"; - jdbcTemplate.update(sql, link.getSoLastEditDate(), link.getSoAnswerCount(), link.getId()); - } - -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java deleted file mode 100644 index fce7af7..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/SubscriptionJdbcTemplateRepository.java +++ /dev/null @@ -1,75 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.repository.jdbc; - - -import lombok.extern.slf4j.Slf4j; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.stereotype.Repository; -import ru.tinkoff.edu.java.scrapper.mapper.LinkRowMapper; -import ru.tinkoff.edu.java.scrapper.mapper.SubscriptionRowMapper; -import ru.tinkoff.edu.java.scrapper.model.Link; -import ru.tinkoff.edu.java.scrapper.model.Relation; -import ru.tinkoff.edu.java.scrapper.model.User; -import ru.tinkoff.edu.java.scrapper.repository.SubscriptionRepository; - -import java.util.List; - -@Repository -@Slf4j -public class SubscriptionJdbcTemplateRepository implements SubscriptionRepository { - - private final JdbcTemplate jdbcTemplate; - - private final SubscriptionRowMapper subscriptionRowMapper; - - private final LinkRowMapper linkRowMapper; - - public SubscriptionJdbcTemplateRepository(JdbcTemplate jdbcTemplate, SubscriptionRowMapper subscriptionRowMapper, LinkRowMapper linkRowMapper) { - this.jdbcTemplate = jdbcTemplate; - this.subscriptionRowMapper = subscriptionRowMapper; - this.linkRowMapper = linkRowMapper; - } - - @Override - public List findLinksByChat(Long chatId) { - log.info("findLinksByChat() method invocation in subscriptionRepo"); - String sql = "select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?"; - return jdbcTemplate.query(sql, linkRowMapper, chatId); - } - - @Override - public List findChatsByLink(Long linkId) { - log.info("findChatsByLink() method invocation in subscriptionRepo"); - String sql = "select * from user_link where user_link.link_id = ?"; - return jdbcTemplate.query(sql, subscriptionRowMapper, linkId); - } - - @Override - public Relation findSubscription(Long linkId, Long chatId) { - log.info("findSubscription() method invocation in subscriptionRepo"); - String sql = "select * from user_link rel where rel.chat_id = ? and rel.link_id = ?"; - List relation = jdbcTemplate.query(sql, subscriptionRowMapper, chatId, linkId); - return relation.size() == 0 ? null : relation.get(0); - } - - - @Override - public void addRelation(Relation relation) { - log.info("addRelation() method invocation in subscriptionRepo"); - String sql = "insert into user_link (link_id, chat_id) values(?, ?)"; - jdbcTemplate.update(sql, relation.getLinkId(), relation.getChatId()); - } - - @Override - public void remove(Long linkId, Long chatId) { - log.info("remove() method invocation in subscriptionRepo"); - String sql = "delete from user_link where user_link.link_id = ? and user_link.chat_id = ?"; - jdbcTemplate.update(sql, linkId, chatId); - } - - @Override - public void removeAllByUser(Long chatId) { - log.info("removeAllByUser() method invocation in subscriptionRepo"); - String sql = "delete from user_link where user_link.chat_id = ?"; - jdbcTemplate.update(sql, chatId); - } -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java deleted file mode 100644 index d59d09c..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbc/UserJdbcTemplateRepository.java +++ /dev/null @@ -1,59 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.repository.jdbc; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.stereotype.Repository; -import ru.tinkoff.edu.java.scrapper.mapper.UserRowMapper; -import ru.tinkoff.edu.java.scrapper.model.User; -import ru.tinkoff.edu.java.scrapper.repository.UserRepository; - -import java.util.List; - -@Repository -@Slf4j -public class UserJdbcTemplateRepository implements UserRepository { - - - private final JdbcTemplate jdbcTemplate; - - private final UserRowMapper userRowMapper; - - - public UserJdbcTemplateRepository(JdbcTemplate jdbcTemplate, UserRowMapper userRowMapper) { - this.jdbcTemplate = jdbcTemplate; - this.userRowMapper = userRowMapper; - } - - @Override - public List findAll(){ - log.info("findAll() method invocation in userRepo"); - String sql = "select * from \"user\""; - return jdbcTemplate.query(sql, userRowMapper); - } - - @Override - public User findByChatId(Long id) { - log.info("findByChatId() method invocation in userRepo"); - String sql = "select * from \"user\" where \"user\".chat_id = ?"; - List user = jdbcTemplate.query(sql, userRowMapper, id); - return user.size() == 0 ? null : user.get(0); - } - - @Override - public void add(User user){ - log.info("add() method invocation in userRepo"); - String sql = "insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)"; - jdbcTemplate.update(sql, user.getChatId(), user.getUsername(), user.getFirstName(), user.getLastName()); - } - - @Override - public void remove(Long chatId){ - log.info("remove() method invocation in userRepo"); - String sql = "delete from \"user\" where \"user\".chat_id = ?"; - jdbcTemplate.update(sql,chatId); - } - - - - -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java deleted file mode 100644 index 0298278..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/LinkRepository.java +++ /dev/null @@ -1,21 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract; - -import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; -import java.util.List; - - -public interface LinkRepository { - List findAll(); - - - Link findByUrl(String url); - void add(Link link); - - void updateCheckDate(Link link); - void remove(Long id); - List findOldLinks(Long timeUpdateDeltaInSeconds); - - void updateGhLink(Link link); - - void updateSoLink(Link link); -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java deleted file mode 100644 index 0dde7e4..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/SubscriptionRepository.java +++ /dev/null @@ -1,19 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract; - -import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; -import ru.tinkoff.edu.java.scrapper.model.jdbcAndJooq.Relation; - -import java.util.List; - -public interface SubscriptionRepository { - - List findLinksByChat(Long chatId); - - List findChatsByLink(Long linkId); - - Relation findSubscription(Long linkId, Long chatId); - void addRelation(Relation relation); - void remove(Long linkId, Long chatId); - - void removeAllByUser(Long chatId); -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java deleted file mode 100644 index 87cbf34..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jdbcAndJooqContract/UserRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract; - -import ru.tinkoff.edu.java.scrapper.model.commonDto.User; -import java.util.List; - -public interface UserRepository { - List findAll(); - - User findByChatId(Long id); - void add(User user); - void remove(Long id); - -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java deleted file mode 100644 index 7371ffd..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/LinkJooqRepository.java +++ /dev/null @@ -1,98 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.repository.jooq; - -import lombok.extern.slf4j.Slf4j; -import org.jooq.DSLContext; -import org.springframework.stereotype.Repository; -import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; -import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.LinkRepository; -import java.sql.Timestamp; -import java.util.List; -import static ru.tinkoff.edu.java.scrapper.domain.jooq.tables.Link.*; - -@Slf4j -public class LinkJooqRepository implements LinkRepository { - - - private final DSLContext dslContext; - - - - public LinkJooqRepository(DSLContext dslContext) { - this.dslContext = dslContext; - } - - @Override - public List findAll() { - log.info("findAll() method invocation in linkJooqRepo"); - return dslContext.selectFrom(LINK) - .fetchInto(Link.class); - } - - @Override - public Link findByUrl(String url) { - log.info("findByUrl() method invocation in linkJooqRepo"); - return dslContext.selectFrom(LINK) - .where(LINK.URL.eq(url)) - .fetchOneInto(Link.class); - } - - @Override - public void add(Link link) { - log.info("add() method invocation in linkJooqRepo"); - dslContext.insertInto(LINK) - .set(LINK.URL, link.getUrl()) - .set(LINK.CHECKED_AT, link.getCheckedAt().toLocalDateTime()) - .execute(); - } - - @Override - public void updateCheckDate(Link link) { - log.info("updateDate() method invocation in linkJooqRepo"); - dslContext.update(LINK) - .set(LINK.CHECKED_AT, link.getCheckedAt().toLocalDateTime()) - .where(LINK.ID.eq(link.getId())) - .execute(); - } - - @Override - public void remove(Long id) { - log.info("remove() method invocation in linkJooqRepo"); - dslContext.deleteFrom(LINK) - .where(LINK.ID.eq(id)) - .execute(); - } - - @Override - public List findOldLinks(Long timeUpdateDeltaInSeconds) { - log.info("findOldLinks() method invocation in linkJooqRepo"); - Timestamp compareDate = new Timestamp(System.currentTimeMillis() - timeUpdateDeltaInSeconds * 1000); - return dslContext.selectFrom(LINK) - .where(LINK.CHECKED_AT.lessThan(compareDate.toLocalDateTime())) - .orderBy(LINK.CHECKED_AT.desc()) - .fetchInto(Link.class); - } - - @Override - public void updateGhLink(Link link) { - log.info("updateGhLink() method invocation in linkJooqRepo"); - dslContext.update(LINK) - .set(LINK.CHECKED_AT, link.getCheckedAt().toLocalDateTime()) - .set(LINK.GH_FORKS_COUNT, link.getGhForksCount()) - .set(LINK.GH_DESCRIPTION, link.getGhDescription()) - .set(LINK.GH_PUSHED_AT, link.getGhPushedAt().toLocalDateTime()) - .where(LINK.ID.eq(link.getId())) - .execute(); - } - - @Override - public void updateSoLink(Link link) { - log.info("updateSoLink() method invocation in linkJooqRepo"); - dslContext.update(LINK) - .set(LINK.CHECKED_AT, link.getCheckedAt().toLocalDateTime()) - .set(LINK.SO_LAST_EDIT_DATE, link.getSoLastEditDate().toLocalDateTime()) - .set(LINK.SO_ANSWER_COUNT, link.getSoAnswerCount()) - .where(LINK.ID.eq(link.getId())) - .execute(); - } - -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java deleted file mode 100644 index 6463de4..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/SubscriptionJooqRepository.java +++ /dev/null @@ -1,80 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.repository.jooq; - -import lombok.extern.slf4j.Slf4j; -import org.jooq.DSLContext; -import org.springframework.stereotype.Repository; -import ru.tinkoff.edu.java.scrapper.model.Link; -import ru.tinkoff.edu.java.scrapper.model.Relation; -import ru.tinkoff.edu.java.scrapper.repository.SubscriptionRepository; - -import java.util.List; - -import static ru.tinkoff.edu.java.scrapper.domain.jooq.tables.UserLink.*; -import static ru.tinkoff.edu.java.scrapper.domain.jooq.tables.Link.*; - - -@Repository -@Slf4j -public class SubscriptionJooqRepository implements SubscriptionRepository { - - - private final DSLContext dslContext; - - - public SubscriptionJooqRepository(DSLContext dslContext) { - this.dslContext = dslContext; - } - - - @Override - public List findLinksByChat(Long chatId) { - log.info("findLinksByChat() method invocation in subscriptionJooqRepo"); - return dslContext.select() - .from(LINK) - .join(USER_LINK).on(LINK.ID.eq(USER_LINK.LINK_ID)) - .where(USER_LINK.CHAT_ID.eq(chatId)) - .fetchInto(Link.class); - } - - @Override - public List findChatsByLink(Long linkId) { - log.info("findChatsByLink() method invocation in subscriptionJooqRepo"); - return dslContext.select() - .from(USER_LINK) - .where(USER_LINK.LINK_ID.eq(linkId)) - .fetchInto(Relation.class); - } - - @Override - public Relation findSubscription(Long linkId, Long chatId) { - log.info("findSubscription() method invocation in subscriptionJooqRepo"); - return dslContext.select() - .from(USER_LINK) - .where(USER_LINK.CHAT_ID.eq(chatId).and(USER_LINK.LINK_ID.eq(linkId))) - .fetchOneInto(Relation.class); - } - - @Override - public void addRelation(Relation relation) { - log.info("addRelation() method invocation in subscriptionJooqRepo"); - dslContext.insertInto(USER_LINK, USER_LINK.LINK_ID, USER_LINK.CHAT_ID) - .values(relation.getLinkId(), relation.getChatId()) - .execute(); - } - - @Override - public void remove(Long linkId, Long chatId) { - log.info("remove() method invocation in subscriptionJooqRepo"); - dslContext.deleteFrom(USER_LINK) - .where(USER_LINK.LINK_ID.eq(linkId).and(USER_LINK.CHAT_ID.eq(chatId))) - .execute(); - } - - @Override - public void removeAllByUser(Long chatId) { - log.info("removeAllByUser() method invocation in subscriptionJooqRepo"); - dslContext.deleteFrom(USER_LINK) - .where(USER_LINK.CHAT_ID.eq(chatId)) - .execute(); - } -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java deleted file mode 100644 index d942314..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jooq/UserJooqRepository.java +++ /dev/null @@ -1,59 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.repository.jooq; - -import lombok.extern.slf4j.Slf4j; -import org.jooq.DSLContext; -import org.springframework.stereotype.Repository; -import ru.tinkoff.edu.java.scrapper.model.commonDto.User; -import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.UserRepository; -import java.util.List; - -import static ru.tinkoff.edu.java.scrapper.domain.jooq.tables.User.*; - -@Repository -@Slf4j -public class UserJooqRepository implements UserRepository { - - private final DSLContext dslContext; - - - public UserJooqRepository(DSLContext dslContext) { - this.dslContext = dslContext; - } - - @Override - public List findAll() { - log.info("findAll() method invocation in userJooqRepo"); - - return dslContext.selectFrom(USER).fetchInto(User.class); - } - - @Override - public User findByChatId(Long id) { - log.info("findByChatId() method invocation in userJooqRepo"); - - return dslContext.selectFrom(USER) - .where(USER.CHAT_ID.eq(id)) - .fetchOneInto(User.class); - } - - @Override - public void add(User user) { - log.info("add() method invocation in userJooqRepo"); - - dslContext.insertInto(USER) - .set(USER.CHAT_ID, user.getChatId()) - .set(USER.USERNAME, user.getUsername()) - .set(USER.FIRST_NAME, user.getFirstName()) - .set(USER.LAST_NAME, user.getLastName()) - .execute(); - } - - @Override - public void remove(Long chatId) { - log.info("remove() method invocation in userJooqRepo"); - - dslContext.deleteFrom(USER) - .where(USER.CHAT_ID.eq(chatId)) - .execute(); - } -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java deleted file mode 100644 index 2f1dab8..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaLinkRepository.java +++ /dev/null @@ -1,20 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.repository.jpa; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity; - -import java.sql.Timestamp; -import java.util.List; -import java.util.Optional; - -public interface JpaLinkRepository extends JpaRepository { - Optional findByUrl(String url); - - @Query("select u.chatId from UserEntity u join u.links l where l.id = :id") - List findChatIdsByLinkId(@Param("id") Long id); - - List findByCheckedAtLessThanOrderByCheckedAtDesc(Timestamp compareDate); - -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java deleted file mode 100644 index cdcb762..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/repository/jpa/JpaUserRepository.java +++ /dev/null @@ -1,22 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.repository.jpa; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity; -import ru.tinkoff.edu.java.scrapper.model.jpa.UserEntity; - -import java.util.List; -import java.util.Optional; - -public interface JpaUserRepository extends JpaRepository { - - @Query("select link from UserEntity u join u.links link where u.chatId = :chatId") - List findAllLinksByChat(@Param("chatId") Long chatId); - - - @Query("select u from UserEntity u join fetch u.links link where u.chatId = :chatId") - Optional findByChatIdWithLinks(@Param("chatId") Long chatId); - - -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java deleted file mode 100644 index 388ebac..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/ChatRestController.java +++ /dev/null @@ -1,30 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.rest; - -import org.springframework.web.bind.annotation.*; -import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService; -import ru.tinkoff.edu.java.scrapper.dto.UserAddDto; -import ru.tinkoff.edu.java.scrapper.model.commonDto.User; - -@RestController -@RequestMapping("/tg-chat") -public class ChatRestController { - - - private final TgChatService chatService; - - public ChatRestController(TgChatService chatService) { - this.chatService = chatService; - } - - @PostMapping(value = "{id}") - public void registerChat(@PathVariable Long id, @RequestBody UserAddDto userAddDto) { - chatService.register(new User(id, userAddDto.username(), userAddDto.firstName(), userAddDto.lastName())); - } - - @DeleteMapping(value = "{id}") - public void deleteChat(@PathVariable Long id) { - chatService.unregister(id); - } - - -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java deleted file mode 100644 index 5aef3ac..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rest/LinkRestController.java +++ /dev/null @@ -1,44 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.rest; - -import org.springframework.web.bind.annotation.*; -import ru.tinkoff.edu.java.scrapper.dto.AddLinkRequest; -import ru.tinkoff.edu.java.scrapper.dto.LinkResponse; -import ru.tinkoff.edu.java.scrapper.dto.ListLinkResponse; -import ru.tinkoff.edu.java.scrapper.dto.RemoveLinkRequest; -import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; -import ru.tinkoff.edu.java.scrapper.service.contract.LinkService; -import ru.tinkoff.edu.java.scrapper.exception.LinkNotFoundException; -import java.net.URI; -import java.util.List; - -@RestController -@RequestMapping("/links") -public class LinkRestController { - - private final SubscriptionService subscriptionService; - - public LinkRestController(SubscriptionService subscriptionService) { - this.subscriptionService = subscriptionService; - } - - @GetMapping - public ListLinkResponse getLinks(@RequestHeader("Tg-Chat-Id") Long chatId) { - List list = subscriptionService.getLinksByChat(chatId); - return new ListLinkResponse(list, list.size()); - } - - @PostMapping - public LinkResponse addLink(@RequestHeader("Tg-Chat-Id") Long chatId, @RequestBody AddLinkRequest request) { - Link link = subscriptionService.subscribe(chatId, URI.create(request.link())); - return new LinkResponse(link.getId(), link.getUrl()); - } - - @DeleteMapping - public LinkResponse deleteLink(@RequestHeader("Tg-Chat-Id") Long chatId, @RequestBody RemoveLinkRequest request) { - Link link = subscriptionService.unsubscribe(chatId, URI.create(request.link())); - if (link == null) throw new LinkNotFoundException("Ссылка с таким url не отслеживается!"); - return new LinkResponse(link.getId(), link.getUrl()); - } - - -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java deleted file mode 100644 index eec99f7..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdateScheduler.java +++ /dev/null @@ -1,26 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.schedule; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Component; -import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService; - -import java.util.List; - -@Slf4j -@Component -public class LinkUpdateScheduler { - - private final LinkUpdateService linkUpdateService; - - - public LinkUpdateScheduler(LinkUpdateService linkUpdateService, Parser_Link linkParser) { - this.linkUpdateService = linkUpdateService; - } - - @Scheduled(fixedDelayString = "#{@schedulerIntervalMs}") - public void update() { - log.info("update() method invocation in LinkUpdateScheduler"); - linkUpdateService.updateLinks(); - } -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdaterScheduler.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdaterScheduler.java new file mode 100644 index 0000000..10c9caa --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdaterScheduler.java @@ -0,0 +1,63 @@ +package ru.tinkoff.edu.java.scrapper.schedule; + +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClientResponseException; +import ru.tinkoff.edu.java.linkparser.LinkParser; +import ru.tinkoff.edu.java.scrapper.client.ClientConfiguration; +import ru.tinkoff.edu.java.scrapper.jdbc.JdbcLinkService; +import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkOperations; + +import java.lang.ref.Cleaner; +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +@Service +public class LinkUpdaterScheduler implements LinkOperations { + private final static Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + + private final JdbcTemplate jdbcTemplate; + ArrayList link_list = new ArrayList<>(); + static int ix = 0; + ClientConfiguration client = new ClientConfiguration(); + LinkParser pars = new LinkParser(); + boolean git_link_is_activity; + boolean stack_link_is_activity; + + public LinkUpdaterScheduler(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Scheduled(fixedDelayString = "${app.scheduler.interval}") + public void update() { + int i; + for (i = 0; i < i_getAllIds(jdbcTemplate).size(); i++){ + if (!link_list.contains(i_getAllIds(jdbcTemplate).get(i).url())) { + link_list.add(i_getAllIds(jdbcTemplate).get(i).url()); + } + } + try { + client.gitHubClient(pars.getLink(link_list.get(ix))); + git_link_is_activity = true; + } catch (WebClientResponseException e) { + git_link_is_activity = false; + } + try { + client.stackOverflowClient(pars.getLink(link_list.get(ix))); + stack_link_is_activity = true; + } catch (WebClientResponseException ignored) { + stack_link_is_activity = false; + } + if (!(git_link_is_activity || stack_link_is_activity)) { + String link = "Ссылка %s устарела"; + link = link.formatted(i_getAllIds(jdbcTemplate).get(ix).url()); + LOGGER.log(Level.INFO, link); + } + ix++; + if (ix == link_list.size()) ix = 0; + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java index 623f12b..d060c22 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/Scheduler.java @@ -2,5 +2,4 @@ import java.time.Duration; -public record Scheduler(Duration interval) { -} \ No newline at end of file +public record Scheduler(Duration interval) {} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java deleted file mode 100644 index 61ee96d..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/UpdateNotificationService.java +++ /dev/null @@ -1,8 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.service; - -import ru.tinkoff.edu.java.scrapper.dto.LinkUpdate; - -public interface UpdateNotificationService { - - void updateLink(LinkUpdate request); -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java deleted file mode 100644 index 10646d7..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/LinkUpdateService.java +++ /dev/null @@ -1,12 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.service.contract; - -import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; -import java.util.List; - -public interface LinkUpdateService { - - - List getOldLinks(); - - void updateLinks(); -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java deleted file mode 100644 index b35caad..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/SubscriptionService.java +++ /dev/null @@ -1,14 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.service.contract; - -import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; -import java.net.URI; -import java.util.List; - -public interface SubscriptionService { - - Link add(Long chatId, URI url); - Link remove(Long chatId, URI url); - - List getAllByUser(Long chatId); - -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java deleted file mode 100644 index adf1fde..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/contract/TgChatService.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.service.contract; - -import ru.tinkoff.edu.java.scrapper.model.commonDto.User; - -public interface TgChatService { - - void register(User user); - - void unregister(Long chatId); - -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java deleted file mode 100644 index 983fdb9..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/LinkUpdateServiceImpl.java +++ /dev/null @@ -1,156 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Primary; -import org.springframework.stereotype.Service; -import ru.tinkoff.edu.java.link_parser.parser.Link_Parser; -import ru.tinkoff.edu.java.link_parser.link.GitHub_Link; -import ru.tinkoff.edu.java.link_parser.link.Parser_Link; -import ru.tinkoff.edu.java.link_parser.link.StackOverflow_Link; -import ru.tinkoff.edu.java.scrapper.client.BotClient; -import ru.tinkoff.edu.java.scrapper.client.GitHubClient; -import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient; -import ru.tinkoff.edu.java.scrapper.dto.GitHubResponse; -import ru.tinkoff.edu.java.scrapper.dto.LinkUpdate; -import ru.tinkoff.edu.java.scrapper.dto.StackOverflowItem; -import ru.tinkoff.edu.java.scrapper.exception.GitHubRequestException; -import ru.tinkoff.edu.java.scrapper.exception.StackOverflowRequestException; -//import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; -//import ru.tinkoff.edu.java.scrapper.model.jdbcAndJooq.Relation; -//import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.LinkRepository; -//import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository; -//import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService; - -import java.sql.Timestamp; -import java.time.ZoneOffset; -import java.util.List; - -@Slf4j -public class LinkUpdateServiceImpl implements LinkUpdateService { - - - @Value("${update.delta.time}") - private Long timeUpdateDeltaInSeconds; - - private final LinkRepository linkRepository; - - private final SubscriptionRepository subscriptionRepository; - - private final Link_Parser linkParser; - - private final GitHubClient gitHubClient; - - private final StackOverflowClient stackOverflowClient; - - private final BotClient botClient; - - - public LinkUpdateServiceImpl(LinkRepository linkRepository, SubscriptionRepository subscriptionRepository, Link_Parser linkParser, GitHubClient gitHubClient, StackOverflowClient stackOverflowClient, BotClient botClient) { - this.linkRepository = linkRepository; - this.subscriptionRepository = subscriptionRepository; - this.linkParser = linkParser; - this.gitHubClient = gitHubClient; - this.stackOverflowClient = stackOverflowClient; - this.botClient = botClient; - } - - @Override - public List getOldLinks() { - return linkRepository.findOldLinks(timeUpdateDeltaInSeconds); - } - - - public void updateLinks() { - List oldLinks = getOldLinks(); - - for (Link link : oldLinks) { - Parser_Link result = linkParser.parseUrl(link.getUrl()); - if (result instanceof GitHub_Link) { - try { - boolean isUpdated = false; - String updateDescription = ""; - - - GitHubResponse response = gitHubClient.fetchRepo(((GithubParseResult) result).username(), ((GithubParseResult) result).repository()); - - - if (response.forksCount() != link.getGhForksCount()) { - isUpdated = true; - if (response.forksCount() < link.getGhForksCount()) { - updateDescription += "В репозитории уменьшилось кол-во форков\n"; - } - if (response.forksCount() > link.getGhForksCount()) { - updateDescription += "В репозитории появились новые форки\n"; - } - link.setGhForksCount(response.forksCount()); - } - - - if (link.getGhDescription() == null || !response.description().equals(link.getGhDescription())) { - if (link.getGhDescription() != null) isUpdated = true; - link.setGhDescription(response.description()); - updateDescription += "В репозитории изменилось описание\n"; - } - - if (link.getGhPushedAt() == null || response.pushedAt().toInstant().isAfter(link.getGhPushedAt().toInstant())) { - if (link.getGhPushedAt() != null) isUpdated = true; - link.setGhPushedAt(new Timestamp(response.pushedAt().toInstant().toEpochMilli())); - updateDescription += "В репозитории появился новый commit\n"; - } - - - linkRepository.updateCheckDate(link); - - if (isUpdated) { - Long[] chats = subscriptionRepository.findChatsByLink(link.getId()).stream().map(Relation::getChatId).toArray(Long[]::new); - botClient.updateLink(new LinkUpdate(link.getId(), link.getUrl(), "Вышли обновления в репозитории:\n"+updateDescription, chats)); - } - - - } catch (GitHubRequestException e) { - log.warn(e.getMessage()); - } - - } else if (result instanceof StackOverflow_Link) { - try { - - boolean isUpdated = false; - String updateDescription = ""; - - - StackOverflowItem response = stackOverflowClient.fetchQuestion(((StackOverflowParseResult) result).id()); - - - if (response.lastEditDate() != null && (link.getSoLastEditDate() == null || response.lastEditDate().isAfter(link.getSoLastEditDate().toLocalDateTime().atOffset(ZoneOffset.UTC)))) { - if (link.getSoLastEditDate() != null) isUpdated = true; - link.setSoLastEditDate(new Timestamp(response.lastEditDate().toInstant().toEpochMilli())); - updateDescription += "Текст вопроса был изменён\n"; - } - - if (response.answerCount() != link.getSoAnswerCount()) { - isUpdated = true; - if (response.answerCount() < link.getSoAnswerCount()) { - updateDescription += "На вопрос уменьшилось кол-во ответов\n"; - } - if (response.answerCount() > link.getSoAnswerCount()) { - updateDescription += "На вопрос появились новые ответы\n"; - } - link.setSoAnswerCount(response.answerCount()); - } - - linkRepository.updateCheckDate(link); - - if (isUpdated) { - - Long[] chats = subscriptionRepository.findChatsByLink(link.getId()).stream().map(Relation::getChatId).toArray(Long[]::new); - botClient.updateLink(new LinkUpdate(link.getId(), link.getUrl(), "Вышли обновления в вопросе:\n"+updateDescription, chats)); - } - - } catch (StackOverflowRequestException e) { - log.warn(e.getMessage()); - } - } - } - } -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java deleted file mode 100644 index 4476e8b..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/SubscriptionServiceImpl.java +++ /dev/null @@ -1,99 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Primary; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; -import ru.tinkoff.edu.java.scrapper.model.jdbcAndJooq.Relation; -import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.LinkRepository; -import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository; -import ru.tinkoff.edu.java.scrapper.service.contract.SubscriptionService; - -import java.net.URI; -import java.sql.Timestamp; -import java.util.List; - - -@Slf4j -public class SubscriptionServiceImpl implements SubscriptionService { - - - private final LinkRepository linkRepository; - - private final SubscriptionRepository subscriptionRepository; - - - - public SubscriptionServiceImpl(LinkRepository linkRepository, SubscriptionRepository subscriptionRepository) { - this.linkRepository = linkRepository; - this.subscriptionRepository = subscriptionRepository; - } - - @Override - @Transactional - public Link subscribe(Long chatId, URI url) { - log.info("subscribe() method invocation in SubscriptionServiceImpl. chatId = "+chatId+" url = "+url.toString()); - Link link = linkRepository.findByUrl(url.toString()); - if (link == null) { - link = new Link(); - link.setUrl(url.toString()); - link.setCheckedAt(new Timestamp(System.currentTimeMillis())); - linkRepository.add(link); - //обращение ниже нужно, чтобы получить id из БД - link = linkRepository.findByUrl(link.getUrl()); - } - Relation relation = subscriptionRepository.findSubscription(link.getId(), chatId); - - if (relation == null) { - relation = new Relation(); - relation.setChatId(chatId); - relation.setLinkId(link.getId()); - subscriptionRepository.addRelation(relation); - } - return link; - } - - @Override - @Transactional - public Link unsubscribe(Long chatId, URI url) { - log.info("unsubscribe() method invocation in SubscriptionServiceImpl. chatId = "+chatId+" url = "+url.toString()); - Link link = linkRepository.findByUrl(url.toString()); - - if (link != null) { -// linkRepository.remove(link.getId()); - subscriptionRepository.remove(link.getId(), chatId); - } - return link; - } - - @Override - public List getLinksByChat(Long chatId) { - log.info("getLinksByChat() method invocation in SubscriptionServiceImpl. chatId = "+chatId); - return subscriptionRepository.findLinksByChat(chatId); - } - - @Override - public List getChatIdsByLink(Long linkId) { - log.info("getChatIdsByLink() method invocation in SubscriptionServiceImpl. linkId = "+linkId); - return null; - } - - @Override - public Link add(Long chatId, URI url) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Link remove(Long chatId, URI url) { - // TODO Auto-generated method stub - return null; - } - - @Override - public List getAllByUser(Long chatId) { - // TODO Auto-generated method stub - return null; - } -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java deleted file mode 100644 index 84a130a..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jdbcAndJooq/impl/TgChatServiceImpl.java +++ /dev/null @@ -1,42 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.service.jdbcAndJooq.impl; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Primary; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import ru.tinkoff.edu.java.scrapper.exception.ChatAlreadyExistException; -import ru.tinkoff.edu.java.scrapper.model.commonDto.User; -import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.SubscriptionRepository; -import ru.tinkoff.edu.java.scrapper.repository.jdbcAndJooqContract.UserRepository; -import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService; - -@Slf4j -public class TgChatServiceImpl implements TgChatService { - - private final UserRepository userRepository; - - private final SubscriptionRepository subscriptionRepository; - - - public TgChatServiceImpl(UserRepository userRepository, SubscriptionRepository subscriptionRepository) { - this.userRepository = userRepository; - this.subscriptionRepository = subscriptionRepository; - } - - @Override - public void register(User user) { - log.info("register() method invocation in TgChatServiceImpl. chatId = "+user.getChatId()); - User userInBd = userRepository.findByChatId(user.getChatId()); - if (userInBd != null) throw new ChatAlreadyExistException(); - userRepository.add(user); - } - - @Override - @Transactional - public void unregister(Long chatId) { - log.info("unregister() method invocation in TgChatServiceImpl. chatId = "+chatId); - userRepository.remove(chatId); - subscriptionRepository.removeAllByUser(chatId); - } - -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java deleted file mode 100644 index f27d081..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaLinkUpdateServiceImpl.java +++ /dev/null @@ -1,174 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.service.jpa.impl; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Primary; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import ru.tinkoff.edu.java.link_parser.parser.Link_Parser; -import ru.tinkoff.edu.java.link_parser.link.GitHub_Link; -import ru.tinkoff.edu.java.link_parser.link.Parser_Link; -import ru.tinkoff.edu.java.link_parser.link.StackOverflow_Link; -import ru.tinkoff.edu.java.scrapper.client.BotClient; -import ru.tinkoff.edu.java.scrapper.client.GitHubClient; -import ru.tinkoff.edu.java.scrapper.client.StackOverflowClient; -import ru.tinkoff.edu.java.scrapper.dto.GitHubResponse; -import ru.tinkoff.edu.java.scrapper.dto.LinkUpdate; -import ru.tinkoff.edu.java.scrapper.dto.StackOverflowItem; -import ru.tinkoff.edu.java.scrapper.exception.GitHubRequestException; -import ru.tinkoff.edu.java.scrapper.exception.StackOverflowRequestException; -import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; -import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity; -import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaLinkRepository; -import ru.tinkoff.edu.java.scrapper.service.contract.LinkUpdateService; - -import java.sql.Timestamp; -import java.time.ZoneOffset; -import java.util.List; - -@Slf4j -public class JpaLinkUpdateServiceImpl implements LinkUpdateService { - - @Value("${update.delta.time}") - private Long timeUpdateDeltaInSeconds; - - private final JpaLinkRepository linkRepository; - - - - private final Link_Parser linkParser; - - private final GitHubClient gitHubClient; - - private final StackOverflowClient stackOverflowClient; - - private final BotClient botClient; - - - public JpaLinkUpdateServiceImpl(JpaLinkRepository linkRepository, LinkParser linkParser, GitHubClient gitHubClient, StackOverflowClient stackOverflowClient, BotClient botClient) { - this.linkRepository = linkRepository; - this.linkParser = linkParser; - this.gitHubClient = gitHubClient; - this.stackOverflowClient = stackOverflowClient; - this.botClient = botClient; - } - - @Override - public List getOldLinks() { - log.info("getOldLinks() method invocation in JpaLinkUpdateServiceImpl"); - Timestamp compareDate = new Timestamp(System.currentTimeMillis() - timeUpdateDeltaInSeconds*1000); - return linkRepository.findByCheckedAtLessThanOrderByCheckedAtDesc(compareDate).stream().map(Link::fromEntity).toList(); - } - - - public List getOldEntityLinks() { - Timestamp compareDate = new Timestamp(System.currentTimeMillis() - timeUpdateDeltaInSeconds*1000); - return linkRepository.findByCheckedAtLessThanOrderByCheckedAtDesc(compareDate); - } - - @Override - @Transactional - public void updateLinks() { - log.info("updateLinks() method invocation in JpaLinkUpdateServiceImpl"); - List oldLinks = getOldEntityLinks(); - - for (LinkEntity link : oldLinks) { - Parser_Link result = linkParser.parseUrl(link.getUrl()); - if (result instanceof GitHub_Link) { - try { - boolean isUpdated = false; - String updateDescription = ""; - - - System.out.println(link.getUrl()); - GitHubResponse response = gitHubClient.fetchRepo(((GitHub_Link) result).username(), ((GithubParseResult) result).repository()); - System.out.println(response); - - - if (link.getGhForksCount() == null || response.forksCount() != link.getGhForksCount()) { - isUpdated = true; - if (link.getGhForksCount() == null) {link.setGhForksCount(0); isUpdated = false;} - if (isUpdated && response.forksCount() < link.getGhForksCount()) { - updateDescription += "В репозитории уменьшилось кол-во форков\n"; - } - if (isUpdated && response.forksCount() > link.getGhForksCount()) { - updateDescription += "В репозитории появились новые форки\n"; - } - link.setGhForksCount(response.forksCount()); - } - - - if (link.getGhDescription() == null || !response.description().equals(link.getGhDescription())) { - if (link.getGhDescription() != null) isUpdated = true; - link.setGhDescription(response.description()); - updateDescription += "В репозитории изменилось описание\n"; - } - - if (link.getGhPushedAt() == null || response.pushedAt().toInstant().isAfter(link.getGhPushedAt().toInstant())) { - if (link.getGhPushedAt() != null) isUpdated = true; - link.setGhPushedAt(new Timestamp(response.pushedAt().toInstant().toEpochMilli())); - updateDescription += "В репозитории появился новый commit\n"; - } - - link.setCheckedAt(new Timestamp(System.currentTimeMillis())); - - linkRepository.save(link); - - if (isUpdated) { - List chatsIds = linkRepository.findChatIdsByLinkId(link.getId()); - botClient.updateLink(new LinkUpdate(link.getId(), link.getUrl(), "Вышли обновления в репозитории:\n"+updateDescription, chatsIds.toArray(new Long[0]))); - } - - - } catch (GitHubRequestException e) { - log.warn(e.getMessage()); - } - - } else if (result instanceof StackOverflow_Link) { - try { - - boolean isUpdated = false; - String updateDescription = ""; - - - System.out.println(link.getUrl()); - StackOverflowItem response = stackOverflowClient.fetchQuestion(((StackOverflowParseResult) result).id()); - System.out.println(response); - - - - if (response.lastEditDate() != null && (link.getSoLastEditDate() == null || response.lastEditDate().isAfter(link.getSoLastEditDate().toLocalDateTime().atOffset(ZoneOffset.UTC)))) { - if (link.getSoLastEditDate() != null) isUpdated = true; - link.setSoLastEditDate(new Timestamp(response.lastEditDate().toInstant().toEpochMilli())); - updateDescription += "Текст вопроса был изменён\n"; - } - - if (link.getSoAnswerCount() == null || response.answerCount() != link.getSoAnswerCount()) { - isUpdated = true; - if (link.getSoAnswerCount() == null) {link.setSoAnswerCount(0); isUpdated = false;} - if (isUpdated && response.answerCount() < link.getSoAnswerCount()) { - updateDescription += "На вопрос уменьшилось кол-во ответов\n"; - } - if (isUpdated && response.answerCount() > link.getSoAnswerCount()) { - updateDescription += "На вопрос появились новые ответы\n"; - } - link.setSoAnswerCount(response.answerCount()); - } - - - link.setCheckedAt(new Timestamp(System.currentTimeMillis())); - - linkRepository.save(link); - - if (isUpdated) { - List chatsIds = linkRepository.findChatIdsByLinkId(link.getId()); - botClient.updateLink(new LinkUpdate(link.getId(), link.getUrl(), "Вышли обновления в вопросе:\n"+updateDescription, chatsIds.toArray(new Long[0]))); - } - - } catch (StackOverflowRequestException e) { - log.warn(e.getMessage()); - } - } - } - } -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java deleted file mode 100644 index c5c9749..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaSubscriptionServiceImpl.java +++ /dev/null @@ -1,100 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.service.jpa.impl; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Primary; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import ru.tinkoff.edu.java.scrapper.exception.ChatNotFoundException; -import ru.tinkoff.edu.java.scrapper.exception.LinkNotFoundException; -import ru.tinkoff.edu.java.scrapper.model.commonDto.Link; -import ru.tinkoff.edu.java.scrapper.model.jpa.LinkEntity; -import ru.tinkoff.edu.java.scrapper.model.jpa.UserEntity; -import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaLinkRepository; -import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaUserRepository; -import ru.tinkoff.edu.java.scrapper.service.contract.SubscriptionService; - -import java.net.URI; -import java.sql.Timestamp; -import java.util.List; -import java.util.Optional; - -@Slf4j -public class JpaSubscriptionServiceImpl implements SubscriptionService { - - private final JpaLinkRepository linkRepository; - - private final JpaUserRepository userRepository; - - public JpaSubscriptionServiceImpl(JpaLinkRepository linkRepository, JpaUserRepository userRepository) { - this.linkRepository = linkRepository; - this.userRepository = userRepository; - } - - - @Override - @Transactional - public Link subscribe(Long chatId, URI url) { - log.info("subscribe() method invocation in JpaSubscriptionServiceImpl. chatId = "+chatId+" url = "+url.toString()); - Optional optionalLink = linkRepository.findByUrl(url.toString()); - LinkEntity linkToAdd = new LinkEntity(); - if (optionalLink.isEmpty()) { - linkToAdd.setUrl(url.toString()); - } else { - linkToAdd = optionalLink.get(); - } - linkToAdd.setCheckedAt(new Timestamp(System.currentTimeMillis())); - linkRepository.save(linkToAdd); - - Optional optionalUser = userRepository.findById(chatId); - if (optionalUser.isEmpty()) throw new ChatNotFoundException("Такой чат не зарегистрирован!"); - UserEntity user = optionalUser.get(); - List userLinks = user.getLinks(); - - if (!userLinks.contains(linkToAdd)) { - userLinks.add(linkToAdd); - } - - userRepository.save(user); - return Link.fromEntity(linkToAdd); - } - - @Override - @Transactional - public Link unsubscribe(Long chatId, URI url) { - log.info("unsubscribe() method invocation in JpaSubscriptionServiceImpl. chatId = "+chatId+" url = "+url.toString()); - Optional optionalUser = userRepository.findByChatIdWithLinks(chatId); - Optional optionalLink = linkRepository.findByUrl(url.toString()); - - - if (optionalUser.isEmpty()) throw new ChatNotFoundException("Такой пользователь не зарегистрирован"); - - UserEntity user = optionalUser.get(); - - List userLinks = user.getLinks(); - - if (optionalLink.isEmpty() || !userLinks.contains(optionalLink.get())) - throw new LinkNotFoundException("Такая ссылка не отслеживается"); - - userLinks.remove(optionalLink.get()); - userRepository.save(user); - - return Link.fromEntity(optionalLink.get()); - } - - @Override - public List getLinksByChat(Long chatId) { - log.info("getAllByUser() method invocation in JpaSubscriptionServiceImpl. chatId = "+chatId); - Optional optionalUser = userRepository.findById(chatId); - if (optionalUser.isEmpty()) throw new ChatNotFoundException("Такой чат не зарегистрирован!"); - return userRepository.findAllLinksByChat(chatId).stream().map(Link::fromEntity).toList(); - } - - - @Override - public List getChatIdsByLink(Long linkId) { - log.info("getChatIdsByLink() method invocation in JpaSubscriptionServiceImpl. linkId = "+linkId); - Optional optionalLink = linkRepository.findById(linkId); - if (optionalLink.isEmpty()) throw new LinkNotFoundException("Такая ссылка не отслеживается"); - return linkRepository.findChatIdsByLinkId(linkId); - } -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java deleted file mode 100644 index b87e274..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/service/jpa/impl/JpaTgChatServiceImpl.java +++ /dev/null @@ -1,43 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.service.jpa.impl; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Primary; -import org.springframework.stereotype.Service; -import ru.tinkoff.edu.java.scrapper.exception.ChatAlreadyExistException; -import ru.tinkoff.edu.java.scrapper.exception.ChatNotFoundException; -import ru.tinkoff.edu.java.scrapper.model.commonDto.User; -import ru.tinkoff.edu.java.scrapper.model.jpa.UserEntity; -import ru.tinkoff.edu.java.scrapper.repository.jpa.JpaUserRepository; -import ru.tinkoff.edu.java.scrapper.service.contract.TgChatService; - -import java.util.Optional; - - -@Slf4j -public class JpaTgChatServiceImpl implements TgChatService { - - private final JpaUserRepository userRepository; - - public JpaTgChatServiceImpl(JpaUserRepository userRepository) { - this.userRepository = userRepository; - } - - @Override - public void register(User user) { - log.info("register() method invocation in JpaTgChatServiceImpl. User chatId = "+user.getChatId()); - Optional optionalUser = userRepository.findById(user.getChatId()); - if (optionalUser.isPresent()) throw new ChatAlreadyExistException("Такой чат уже зарегистрирован!"); - userRepository.save(User.toEntity(user)); - } - - @Override - public void unregister(Long chatId) { - log.info("unregister() method invocation in JpaTgChatServiceImpl. User chatId = "+chatId); - Optional optionalUser = userRepository.findById(chatId); - if (optionalUser.isEmpty()) throw new ChatNotFoundException("Такой чат не зарегистрирован!"); - userRepository.delete(optionalUser.get()); - } - - - -} \ No newline at end of file diff --git a/FP/scrapper/src/main/resources/application.properties b/FP/scrapper/src/main/resources/application.properties index 3761f00..00d78d2 100644 --- a/FP/scrapper/src/main/resources/application.properties +++ b/FP/scrapper/src/main/resources/application.properties @@ -1,23 +1,5 @@ -server.port=8080 -app.test=beamer-scrapper -gh.baseurl=https://api.github.com -so.baseurl=https://api.stackexchange.com/2.3/ -bot.baseurl=http://localhost:8081 -app.scheduler.interval=61000 -update.delta.time=20 +app.test=123 springdoc.swagger-ui.path=/swagger-ui - -spring.datasource.driver-class-name=org.postgresql.Driver -spring.datasource.url=jdbc:postgresql://localhost:5432/scrapper -spring.datasource.username=romanova -spring.datasource.password=12345654321 -spring.jpa.properties.hibernate.show_sql=true - -spring.rabbitmq.host=localhost -spring.rabbitmq.port=5672 -spring.rabbitmq.username=romanova -spring.rabbitmq.password=12345654321 -app.queue-name=scrapper-bot-queue -app.exchange-name=scrapper-bot-exchange -app.routing-key=scrapper-bot-key -app.use-queue=true +app.scheduler.interval=5000 +git.link=https://github.com/Ray-Not/JavaGuava +stack.link=https://stackoverflow.com/questions/1642028/what-is-the-operator-in-c diff --git a/FP/scrapper/src/main/resources/logback-test.xml b/FP/scrapper/src/main/resources/logback-test.xml deleted file mode 100644 index 900637e..0000000 --- a/FP/scrapper/src/main/resources/logback-test.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n - - - - - - - - - - - - -. diff --git a/FP/scrapper/src/main/resources/scrapperapi.yml b/FP/scrapper/src/main/resources/scrapperapi.yml new file mode 100644 index 0000000..c98cf7d --- /dev/null +++ b/FP/scrapper/src/main/resources/scrapperapi.yml @@ -0,0 +1,184 @@ +openapi: 3.0.1 +info: + title: Scrapper API + version: 1.0.0 + contact: + name: Alexander Biryukov + url: https://github.com +paths: + /tg-chat/{id}: + post: + summary: Зарегистрировать чат + parameters: + - name: id + in: path + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: Чат зарегистрирован + '400': + description: Некорректные параметры запроса + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorResponse' + delete: + summary: Удалить чат + parameters: + - name: id + in: path + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: Чат успешно удалён + '400': + description: Некорректные параметры запроса + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorResponse' + '404': + description: Чат не существует + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorResponse' + /links: + get: + summary: Получить все отслеживаемые ссылки + parameters: + - name: Tg-Chat-Id + in: header + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: Ссылки успешно получены + content: + application/json: + schema: + $ref: '#/components/schemas/ListLinksResponse' + '400': + description: Некорректные параметры запроса + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorResponse' + post: + summary: Добавить отслеживание ссылки + parameters: + - name: Tg-Chat-Id + in: header + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AddLinkRequest' + required: true + responses: + '200': + description: Ссылка успешно добавлена + content: + application/json: + schema: + $ref: '#/components/schemas/LinkResponse' + '400': + description: Некорректные параметры запроса + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorResponse' + delete: + summary: Убрать отслеживание ссылки + parameters: + - name: Tg-Chat-Id + in: header + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RemoveLinkRequest' + required: true + responses: + '200': + description: Ссылка успешно убрана + content: + application/json: + schema: + $ref: '#/components/schemas/LinkResponse' + '400': + description: Некорректные параметры запроса + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorResponse' + '404': + description: Ссылка не найдена + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorResponse' +components: + schemas: + LinkResponse: + type: object + properties: + id: + type: integer + format: int64 + url: + type: string + format: uri + ApiErrorResponse: + type: object + properties: + description: + type: string + code: + type: string + exceptionName: + type: string + exceptionMessage: + type: string + stacktrace: + type: array + items: + type: string + AddLinkRequest: + type: object + properties: + link: + type: string + format: uri + ListLinksResponse: + type: object + properties: + links: + type: array + items: + $ref: '#/components/schemas/LinkResponse' + size: + type: integer + format: int32 + RemoveLinkRequest: + type: object + properties: + link: + type: string + format: uri diff --git a/FP/scrapper/src/test/java/BaseTest.java b/FP/scrapper/src/test/java/BaseTest.java new file mode 100644 index 0000000..447e5c5 --- /dev/null +++ b/FP/scrapper/src/test/java/BaseTest.java @@ -0,0 +1,11 @@ +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class BaseTest extends IntegrationEnvironment { + + @Test + void create_test() { + Assertions.assertTrue(Postgre_container.isCreated()); + System.out.println(Postgre_container.getImage()); + } +} \ No newline at end of file diff --git a/FP/scrapper/src/test/java/IntegrationEnvironment.java b/FP/scrapper/src/test/java/IntegrationEnvironment.java new file mode 100644 index 0000000..7fef825 --- /dev/null +++ b/FP/scrapper/src/test/java/IntegrationEnvironment.java @@ -0,0 +1,45 @@ +import liquibase.Contexts; +import liquibase.LabelExpression; +import liquibase.Liquibase; +import liquibase.database.Database; +import liquibase.database.DatabaseFactory; +import liquibase.database.jvm.JdbcConnection; +import liquibase.exception.LiquibaseException; +import liquibase.resource.DirectoryResourceAccessor; +import org.testcontainers.containers.PostgreSQLContainer; + +import java.io.FileNotFoundException; +import java.nio.file.Path; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +public abstract class IntegrationEnvironment { + + static final protected PostgreSQLContainer Postgre_container; + + static { + Postgre_container = new PostgreSQLContainer<>("postgres:14"); + Postgre_container.start(); + + try { + Connection connection = DriverManager.getConnection( + Postgre_container.getJdbcUrl(), + Postgre_container.getUsername(), + Postgre_container.getPassword()); + Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection)); + Liquibase liquibase = new liquibase.Liquibase( + "master.xml", + new DirectoryResourceAccessor(Path.of(".") + .toAbsolutePath() + .getParent() + .getParent() + .resolve("migrations")), + database); + liquibase.update(new Contexts(), new LabelExpression()); + } catch (SQLException | LiquibaseException | FileNotFoundException e) { + System.out.println(e.getMessage()); + throw new RuntimeException(e); + } + } +} diff --git a/FP/scrapper/src/test/java/JdbcAddTest.java b/FP/scrapper/src/test/java/JdbcAddTest.java new file mode 100644 index 0000000..d5de9ec --- /dev/null +++ b/FP/scrapper/src/test/java/JdbcAddTest.java @@ -0,0 +1,9 @@ +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class JdbcAddTest extends IntegrationEnvironment { + @Test + void create_test() { +// Postgre_container. + } +} diff --git a/FP/scrapper/src/test/java/scrapper/DatabaseTest.java b/FP/scrapper/src/test/java/scrapper/DatabaseTest.java deleted file mode 100644 index 1c2378c..0000000 --- a/FP/scrapper/src/test/java/scrapper/DatabaseTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package scrapper; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.sql.*; - -public class DatabaseTest extends IntegrationEnvironment{ - - - @Test - @DisplayName("Тест для проверки запуска контейнера с PostgreSQL") - public void testIfContainerIsRunning() { - Assertions.assertTrue(POSTGRES_CONTAINER.isRunning(),"Ошибка запуска контейнера PostgreSQL"); - } - - @Test - @DisplayName("Тест для проверки успешного применения миграций") - void testMigrations() throws SQLException { - try (Connection conn = DriverManager.getConnection(IntegrationEnvironment.POSTGRES_CONTAINER.getJdbcUrl(), - IntegrationEnvironment.POSTGRES_CONTAINER.getUsername(), - IntegrationEnvironment.POSTGRES_CONTAINER.getPassword()); - Statement statement = conn.createStatement()) { - - ResultSet resultSetUser = statement.executeQuery("SELECT * FROM \"user\""); - Assertions.assertFalse(resultSetUser.next(), "Таблица user не создана"); - ResultSet resultSetLink = statement.executeQuery("SELECT * FROM \"link\""); - Assertions.assertFalse(resultSetLink.next(), "Таблица link не создана"); - ResultSet resultSetUserLink = statement.executeQuery("SELECT * FROM \"user_link\""); - Assertions.assertFalse(resultSetUserLink.next(),"Таблица user_link не создана"); - } - } - - - - -} \ No newline at end of file diff --git a/FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java b/FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java deleted file mode 100644 index 2f0bdfa..0000000 --- a/FP/scrapper/src/test/java/scrapper/IntegrationEnvironment.java +++ /dev/null @@ -1,54 +0,0 @@ -package scrapper; - -import liquibase.Contexts; -import liquibase.LabelExpression; -import liquibase.Liquibase; -import liquibase.database.Database; -import liquibase.database.DatabaseFactory; -import liquibase.database.jvm.JdbcConnection; -import liquibase.exception.LiquibaseException; -import liquibase.resource.DirectoryResourceAccessor; -import org.testcontainers.containers.PostgreSQLContainer; -import org.testcontainers.junit.jupiter.Testcontainers; - -import java.io.File; -import java.io.FileNotFoundException; -import java.nio.file.Path; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; - -abstract class IntegrationEnvironment { - - static final String IMAGE_VERSION = "postgres:15"; - - static final PostgreSQLContainer POSTGRES_CONTAINER; - - static { - POSTGRES_CONTAINER = new PostgreSQLContainer(IMAGE_VERSION) - .withDatabaseName("scrapper") - .withUsername("lwbeamer") - .withPassword("2281337"); - - - POSTGRES_CONTAINER.start(); - executeMigrations(); - } - - private static void executeMigrations() { - try (Connection conn = DriverManager.getConnection(IntegrationEnvironment.POSTGRES_CONTAINER.getJdbcUrl(), IntegrationEnvironment.POSTGRES_CONTAINER.getUsername(), - IntegrationEnvironment.POSTGRES_CONTAINER.getPassword())) { - Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(conn)); - Path changeLogFile = new File("").toPath().toAbsolutePath().getParent().resolve("migrations"); - Liquibase liquibase = new Liquibase("master.xml",new DirectoryResourceAccessor(changeLogFile), database); - liquibase.update(new Contexts(), new LabelExpression()); - } catch (SQLException | LiquibaseException e) { - throw new RuntimeException("Failed to execute migrations", e); - } catch (FileNotFoundException e) { - throw new RuntimeException("Changelog file not found",e); - } - } - - public static void stopContainer() { - POSTGRES_CONTAINER.stop(); - } diff --git a/FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java b/FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java deleted file mode 100644 index d0ac18a..0000000 --- a/FP/scrapper/src/test/java/scrapper/environment/DatabaseTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package scrapper.environment; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.sql.*; - -public class DatabaseTest extends IntegrationEnvironment{ - - - @Test - @DisplayName("Тест для проверки запуска контейнера с PostgreSQL") - public void testIfContainerIsRunning() { - Assertions.assertTrue(POSTGRES_CONTAINER.isRunning(),"Ошибка запуска контейнера PostgreSQL"); - } - - @Test - @DisplayName("Тест для проверки успешного применения миграций") - void testMigrations() throws SQLException { - try (Connection conn = DriverManager.getConnection(IntegrationEnvironment.POSTGRES_CONTAINER.getJdbcUrl(), - IntegrationEnvironment.POSTGRES_CONTAINER.getUsername(), - IntegrationEnvironment.POSTGRES_CONTAINER.getPassword()); - Statement statement = conn.createStatement()) { - - ResultSet resultSetUser = statement.executeQuery("SELECT * FROM \"user\""); - Assertions.assertFalse(resultSetUser.next(), "Таблица user не создана"); - ResultSet resultSetLink = statement.executeQuery("SELECT * FROM \"link\""); - Assertions.assertFalse(resultSetLink.next(), "Таблица link не создана"); - ResultSet resultSetUserLink = statement.executeQuery("SELECT * FROM \"user_link\""); - Assertions.assertFalse(resultSetUserLink.next(),"Таблица user_link не создана"); - } - } - - - - -} \ No newline at end of file diff --git a/FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java b/FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java deleted file mode 100644 index 416b086..0000000 --- a/FP/scrapper/src/test/java/scrapper/environment/IntegrationEnvironment.java +++ /dev/null @@ -1,81 +0,0 @@ -package scrapper.environment; - -import liquibase.Contexts; -import liquibase.LabelExpression; -import liquibase.Liquibase; -import liquibase.database.Database; -import liquibase.database.DatabaseFactory; -import liquibase.database.jvm.JdbcConnection; -import liquibase.exception.LiquibaseException; -import liquibase.resource.DirectoryResourceAccessor; -import org.springframework.boot.jdbc.DataSourceBuilder; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.test.context.ContextConfiguration; -import org.testcontainers.containers.PostgreSQLContainer; - -import javax.sql.DataSource; -import java.io.File; -import java.io.FileNotFoundException; -import java.nio.file.Path; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; - -@ContextConfiguration(classes = IntegrationEnvironment.EnvironmentConfiguration.class) -public abstract class IntegrationEnvironment { - - - @Configuration - static class EnvironmentConfiguration{ - @Bean - public DataSource dataSource() { - return DataSourceBuilder.create() - .url(POSTGRES_CONTAINER.getJdbcUrl()) - .username(POSTGRES_CONTAINER.getUsername()) - .password(POSTGRES_CONTAINER.getPassword()) - .build(); - } - - @Bean - public JdbcTemplate jdbcTemplate(DataSource dataSource){ - return new JdbcTemplate(dataSource); - } - - } - - static final String IMAGE_VERSION = "postgres:15"; - - static final PostgreSQLContainer POSTGRES_CONTAINER; - - static { - POSTGRES_CONTAINER = new PostgreSQLContainer(IMAGE_VERSION) - .withDatabaseName("scrapper") - .withUsername("lwbeamer") - .withPassword("2281337"); - - - POSTGRES_CONTAINER.start(); - executeMigrations(); - } - - private static void executeMigrations() { - try (Connection conn = DriverManager.getConnection(IntegrationEnvironment.POSTGRES_CONTAINER.getJdbcUrl(), IntegrationEnvironment.POSTGRES_CONTAINER.getUsername(), - IntegrationEnvironment.POSTGRES_CONTAINER.getPassword())) { - Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(conn)); - Path changeLogFile = new File("").toPath().toAbsolutePath().getParent().resolve("migrations"); - Liquibase liquibase = new Liquibase("master.xml",new DirectoryResourceAccessor(changeLogFile), database); - liquibase.update(new Contexts(), new LabelExpression()); - } catch (SQLException | LiquibaseException e) { - throw new RuntimeException("Failed to execute migrations", e); - } catch (FileNotFoundException e) { - throw new RuntimeException("Changelog file not found",e); - } - } - - public static void stopContainer() { - POSTGRES_CONTAINER.stop(); - } - -} \ No newline at end of file diff --git a/FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java b/FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java deleted file mode 100644 index a4ff395..0000000 --- a/FP/scrapper/src/test/java/scrapper/environment/TestConfiguration.java +++ /dev/null @@ -1,8 +0,0 @@ -package scrapper.environment; - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration; - -@EnableAutoConfiguration(exclude = { LiquibaseAutoConfiguration.class }) -public class TestConfiguration { -} \ No newline at end of file diff --git a/FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java b/FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java deleted file mode 100644 index 436f01a..0000000 --- a/FP/scrapper/src/test/java/scrapper/jdbc/JdbcLinkTest.java +++ /dev/null @@ -1,151 +0,0 @@ -package scrapper.jdbc; - -import scrapper.environment.IntegrationEnvironment; -import scrapper.environment.TestConfiguration; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.test.annotation.Rollback; -import org.springframework.transaction.annotation.Transactional; -import ru.tinkoff.edu.java.scrapper.ScrapperApplication; -import ru.tinkoff.edu.java.scrapper.mapper.LinkRowMapper; -import ru.tinkoff.edu.java.scrapper.model.Link; -import ru.tinkoff.edu.java.scrapper.repository.*; -import ru.tinkoff.edu.java.scrapper.repository.jdbc.LinkJdbcTemplateRepository; - -import java.sql.Timestamp; -import java.util.List; - -@SpringBootTest(classes = {ScrapperApplication.class, TestConfiguration.class}) -public class JdbcLinkTest extends IntegrationEnvironment { - - @Autowired - private LinkJdbcTemplateRepository linkRepository; - - @Autowired - private LinkRowMapper linkRowMapper; - - @Autowired - private JdbcTemplate jdbcTemplate; - - - @Test - @Transactional - @Rollback - public void addLinkTest() { - List beforeAddLink = jdbcTemplate.query("select * from link where link.url='https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file'", linkRowMapper); - - Link linkToAdd = new Link(); - linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file"); - linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis())); - linkRepository.add(linkToAdd); - - List addedLink = jdbcTemplate.query("select * from link where link.url='https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file'", linkRowMapper); - - Assertions.assertEquals(beforeAddLink.size(), 0); - Assertions.assertNotNull(addedLink.get(0)); - Assertions.assertEquals("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file", addedLink.get(0).getUrl()); - } - - - @Test - @Transactional - @Rollback - public void removeLinkTest() { - List beforeAddLink = jdbcTemplate.query("select * from link where link.url='https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file'", linkRowMapper); - - Link linkToAdd = new Link(); - linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file"); - linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis())); - jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt()); - - List afterInsertionLink = jdbcTemplate.query("select * from link where link.url='https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file'", linkRowMapper); - - linkRepository.remove(afterInsertionLink.get(0).getId()); - - List afterRemovingLink = jdbcTemplate.query("select * from link where link.url='https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file'", linkRowMapper); - - - Assertions.assertEquals(beforeAddLink.size(), 0); - Assertions.assertEquals(afterInsertionLink.size(), 1); - Assertions.assertEquals(afterRemovingLink.size(), 0); - } - - - @Test - @Transactional - @Rollback - public void findAllTest() { - List beforeAddLink = jdbcTemplate.query("select * from link", linkRowMapper); - - for (int i = 0; i < 10; i++) { - Link linkToAdd = new Link(); - linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i); - linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis())); - jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt()); - } - - List afterInsertionLink = linkRepository.findAll(); - - Assertions.assertEquals(beforeAddLink.size(), 0); - Assertions.assertEquals(afterInsertionLink.size(), 10); - } - - - @Test - @Transactional - @Rollback - public void findByUrlTest(){ - List beforeAddLink = jdbcTemplate.query("select * from link", linkRowMapper); - - for (int i = 0; i < 10; i++) { - Link linkToAdd = new Link(); - linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i); - linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis())); - jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt()); - } - - List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper); - Link foundedByUrlLink = linkRepository.findByUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file0"); - - Assertions.assertEquals(beforeAddLink.size(), 0); - Assertions.assertEquals(afterInsertionLink.size(), 10); - Assertions.assertNotNull(foundedByUrlLink); - } - - - @Test - @Transactional - @Rollback - public void updateDateTest(){ - List beforeAddLink = jdbcTemplate.query("select * from link", linkRowMapper); - - - Link linkToAdd = new Link(); - linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file"); - Timestamp timestampBefore = new Timestamp(System.currentTimeMillis()); - linkToAdd.setUpdatedAt(timestampBefore); - jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt()); - - - List linkBeforeUpdate = jdbcTemplate.query("select * from link where link.url = ?", linkRowMapper, "https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file"); - - Assertions.assertEquals(linkBeforeUpdate.get(0).getUpdatedAt(),timestampBefore); - - linkBeforeUpdate.get(0).setUpdatedAt(new Timestamp(100000)); - - linkRepository.updateDate(linkBeforeUpdate.get(0)); - - List linkAfterUpdate = jdbcTemplate.query("select * from link where link.url = ?", linkRowMapper, "https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file"); - - Assertions.assertEquals(beforeAddLink.size(), 0); - Assertions.assertEquals(linkAfterUpdate.get(0).getUpdatedAt(),new Timestamp(100000)); - } - - - - - -} \ No newline at end of file diff --git a/FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java b/FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java deleted file mode 100644 index 0813c59..0000000 --- a/FP/scrapper/src/test/java/scrapper/jdbc/JdbcSubscriptionTest.java +++ /dev/null @@ -1,251 +0,0 @@ -package scrapper.jdbc; - -import scrapper.environment.IntegrationEnvironment; -import scrapper.environment.TestConfiguration; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.test.annotation.Rollback; -import org.springframework.transaction.annotation.Transactional; -import ru.tinkoff.edu.java.scrapper.ScrapperApplication; -import ru.tinkoff.edu.java.scrapper.mapper.LinkRowMapper; -import ru.tinkoff.edu.java.scrapper.mapper.SubscriptionRowMapper; -import ru.tinkoff.edu.java.scrapper.model.Link; -import ru.tinkoff.edu.java.scrapper.model.Relation; -import ru.tinkoff.edu.java.scrapper.model.User; -import ru.tinkoff.edu.java.scrapper.repository.jdbc.LinkJdbcTemplateRepository; -import ru.tinkoff.edu.java.scrapper.repository.jdbc.SubscriptionJdbcTemplateRepository; - -import java.sql.Timestamp; -import java.util.List; - -@SpringBootTest(classes = {ScrapperApplication.class, TestConfiguration.class}) -public class JdbcSubscriptionTest extends IntegrationEnvironment { - - @Autowired - private SubscriptionJdbcTemplateRepository subscriptionRepository; - - @Autowired - private LinkRowMapper linkRowMapper; - - @Autowired - private SubscriptionRowMapper subscriptionRowMapper; - - @Autowired - private JdbcTemplate jdbcTemplate; - - - @Test - @Transactional - @Rollback - public void findLinksByChatTest() { - List beforeAddLink = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L); - - jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 42L, "robtop21", "Robert", "Polson"); - jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 50L, "alucard", "Will", "Smith"); - - //всего добавим 20 ссылок - for (int i = 0; i < 20; i++) { - Link linkToAdd = new Link(); - linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i); - linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis())); - jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt()); - } - - List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper); - - //из 20-ти ссылок подпишемся лишь на 10 - for (int i = 0; i < 10; i++) { - jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(i).getId(), 42L); - } - - //на оставшиеся 10 подпишем другого пользователя - for (int i = 10; i < 20; i++) { - jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(i).getId(), 50L); - } - - List userLinks = subscriptionRepository.findLinksByChat(42L); - - Assertions.assertEquals(beforeAddLink.size(), 0); - Assertions.assertEquals(afterInsertionLink.size(), 20); - Assertions.assertEquals(userLinks.size(), 10); - } - - @Test - @Transactional - @Rollback - public void removeRelationTest() { - List beforeAddLink = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L); - - jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 42L, "robtop21", "Robert", "Polson"); - - for (int i = 0; i < 20; i++) { - Link linkToAdd = new Link(); - linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i); - linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis())); - jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt()); - } - - List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper); - - for (int i = 0; i < 10; i++) { - jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(i).getId(), 42L); - } - - List userLinksBeforeRemove = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L); - - subscriptionRepository.remove(afterInsertionLink.get(0).getId(), 42L); - subscriptionRepository.remove(afterInsertionLink.get(4).getId(), 42L); - subscriptionRepository.remove(afterInsertionLink.get(6).getId(), 42L); - - List userLinksAfterRemove = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L); - - Assertions.assertEquals(beforeAddLink.size(), 0); - Assertions.assertEquals(afterInsertionLink.size(), 20); - Assertions.assertEquals(userLinksBeforeRemove.size(), 10); - Assertions.assertEquals(userLinksAfterRemove.size(), 7); - } - - - @Test - @Transactional - @Rollback - public void addRelationTest() { - List beforeAddLink = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L); - - jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 42L, "robtop21", "Robert", "Polson"); - - for (int i = 0; i < 20; i++) { - Link linkToAdd = new Link(); - linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i); - linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis())); - jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt()); - } - - List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper); - - for (int i = 0; i < 10; i++) { - Relation relation = new Relation(); - relation.setLinkId(afterInsertionLink.get(i).getId()); - relation.setChatId(42L); - subscriptionRepository.addRelation(relation); - } - - - List userLinks = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L); - - Assertions.assertEquals(beforeAddLink.size(), 0); - Assertions.assertEquals(afterInsertionLink.size(), 20); - Assertions.assertEquals(userLinks.size(), 10); - } - - - @Test - @Transactional - @Rollback - public void findChatsByLinkTest() { - List beforeAddRelation = jdbcTemplate.query("select * from user_link", subscriptionRowMapper); - - - for (int i = 0; i < 10; i++) { - User user = new User(42L + i, "robtop21" + i, "Robert", "Polson"); - - jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", - user.getChatId(), - user.getUsername(), - user.getFirstName(), - user.getLastName()); - } - - - Link linkToAdd = new Link(); - linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file"); - linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis())); - jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt()); - - List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper); - - - for (int i = 0; i < 7; i++) { - Relation relation = new Relation(); - relation.setLinkId(afterInsertionLink.get(0).getId()); - relation.setChatId(42L + i); - subscriptionRepository.addRelation(relation); - } - - List afterSubscribe = subscriptionRepository.findChatsByLink(afterInsertionLink.get(0).getId()); - - Assertions.assertEquals(beforeAddRelation.size(), 0); - Assertions.assertEquals(afterSubscribe.size(), 7); - } - - @Test - @Transactional - @Rollback - public void findSubscriptionTest() { - List beforeAddRelation = jdbcTemplate.query("select * from user_link", subscriptionRowMapper); - - jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 42L, "robtop21", "Robert", "Polson"); - - - Link linkToAdd = new Link(); - linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file"); - linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis())); - jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt()); - List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper); - jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(0).getId(), 42L); - - Relation relation = subscriptionRepository.findSubscription(afterInsertionLink.get(0).getId(), 42L); - - - Assertions.assertEquals(beforeAddRelation.size(),0); - Assertions.assertEquals(afterInsertionLink.size(),1); - Assertions.assertNotNull(relation); - } - - - @Test - @Transactional - @Rollback - public void removeAllByUserTest(){ - List beforeAddRelation = jdbcTemplate.query("select * from user_link", subscriptionRowMapper); - - - jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 42L, "robtop21", "Robert", "Polson"); - jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", 50L, "alucard", "Will", "Smith"); - - //всего добавим 20 ссылок - for (int i = 0; i < 20; i++) { - Link linkToAdd = new Link(); - linkToAdd.setUrl("https://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file" + i); - linkToAdd.setUpdatedAt(new Timestamp(System.currentTimeMillis())); - jdbcTemplate.update("insert into link (url, updated_at) values(?, ?)", linkToAdd.getUrl(), linkToAdd.getUpdatedAt()); - } - - List afterInsertionLink = jdbcTemplate.query("select * from link", linkRowMapper); - - //из 20-ти ссылок подпишемся лишь на 10 - for (int i = 0; i < 10; i++) { - jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(i).getId(), 42L); - } - - //на оставшиеся 10 подпишем другого пользователя - for (int i = 10; i < 20; i++) { - jdbcTemplate.update("insert into user_link (link_id, chat_id) values(?, ?)", afterInsertionLink.get(i).getId(), 50L); - } - - List userLinksBeforeDelete = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L); - - subscriptionRepository.removeAllByUser(42L); - - List userLinksAfterDelete = jdbcTemplate.query("select * from link inner join user_link rel on link.id = rel.link_id where rel.chat_id = ?", linkRowMapper, 42L); - - Assertions.assertEquals(beforeAddRelation.size(),0); - Assertions.assertEquals(afterInsertionLink.size(), 20); - Assertions.assertEquals(userLinksBeforeDelete.size(), 10); - Assertions.assertEquals(userLinksAfterDelete.size(), 0); - } - -} diff --git a/FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java b/FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java deleted file mode 100644 index df7d245..0000000 --- a/FP/scrapper/src/test/java/scrapper/jdbc/JdbcUserTest.java +++ /dev/null @@ -1,135 +0,0 @@ -package scrapper.jdbc; - -import scrapper.environment.IntegrationEnvironment; -import scrapper.environment.TestConfiguration; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.test.annotation.Rollback; -import org.springframework.transaction.annotation.Transactional; -import ru.tinkoff.edu.java.scrapper.ScrapperApplication; -import ru.tinkoff.edu.java.scrapper.mapper.UserRowMapper; -import ru.tinkoff.edu.java.scrapper.model.User; -import ru.tinkoff.edu.java.scrapper.repository.jdbc.UserJdbcTemplateRepository; - -import java.util.List; - -@SpringBootTest(classes = {ScrapperApplication.class, TestConfiguration.class}) -public class JdbcUserTest extends IntegrationEnvironment { - - @Autowired - private UserJdbcTemplateRepository userRepository; - - @Autowired - private UserRowMapper userRowMapper; - - @Autowired - private JdbcTemplate jdbcTemplate; - - - @Test - @Transactional - @Rollback - public void addUserTest() { - List beforeAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper); - - User user = new User(42L, "robtop21", "Robert","Polson"); - - - userRepository.add(user); - - List afterAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper); - - Assertions.assertEquals(beforeAddUser.size(), 0); - Assertions.assertEquals(afterAddUser.size(), 1); - Assertions.assertNotNull(afterAddUser.get(0)); - Assertions.assertEquals(afterAddUser.get(0).getChatId(), 42L); - } - - - @Test - @Transactional - @Rollback - public void removeUserTest() { - List beforeAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper); - - User user = new User(42L, "robtop21", "Robert","Polson"); - - - - jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", - user.getChatId(), - user.getUsername(), - user.getFirstName(), - user.getLastName()); - - - List afterAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper); - - userRepository.remove(42L); - - List afterRemoveUser = jdbcTemplate.query("select * from \"user\"", userRowMapper); - - - Assertions.assertEquals(beforeAddUser.size(), 0); - Assertions.assertEquals(afterAddUser.size(), 1); - Assertions.assertNotNull(afterAddUser.get(0)); - Assertions.assertEquals(afterAddUser.get(0).getChatId(), 42L); - Assertions.assertEquals(afterRemoveUser.size(), 0); - } - - @Test - @Transactional - @Rollback - public void findAllTest() { - List beforeAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper); - - - for (int i = 0; i < 10; i++) { - User user = new User(42L + i, "robtop21" + i, "Robert","Polson"); - - jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", - user.getChatId(), - user.getUsername(), - user.getFirstName(), - user.getLastName()); - } - - List afterInsertionUser = userRepository.findAll(); - - Assertions.assertEquals(beforeAddUser.size(), 0); - Assertions.assertEquals(afterInsertionUser.size(), 10); - } - - - @Test - @Transactional - @Rollback - public void findByChatIdTest(){ - List beforeAddUser = jdbcTemplate.query("select * from \"user\"", userRowMapper); - - - for (int i = 0; i < 10; i++) { - User user = new User(42L + i, "robtop21" + i, "Robert","Polson"); - - jdbcTemplate.update("insert into \"user\" (chat_id, username, first_name, last_name) values(?, ?, ?, ?)", - user.getChatId(), - user.getUsername(), - user.getFirstName(), - user.getLastName()); - } - - List afterInsertionUser = jdbcTemplate.query("select * from \"user\"", userRowMapper); - - User foundedByIdUser = userRepository.findByChatId(42L); - - Assertions.assertEquals(beforeAddUser.size(), 0); - Assertions.assertEquals(afterInsertionUser.size(), 10); - Assertions.assertNotNull(foundedByIdUser); - - } - - -} \ No newline at end of file diff --git a/README.md b/README.md index dbfb550..e69de29 100644 --- a/README.md +++ b/README.md @@ -1 +0,0 @@ -# JavaGuava From 5cc44299996fe74ceebdf1b339c104bd71785041 Mon Sep 17 00:00:00 2001 From: Ray-Not <2sinsincuba@gmail.com> Date: Fri, 19 May 2023 04:09:08 +0500 Subject: [PATCH 5/9] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20RabbitConfig=20=D0=B8=20=D0=BE=D1=81=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=D0=BD=D1=8B=D1=85=20=D1=84=D0=B0=D0=B9=D0=BB=D0=BE?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FP/bot/pom.xml | 8 ++- .../tinkoff/edu/java/bot/BotApplication.java | 5 +- .../edu/java/bot/api/BotController.java | 2 +- .../exceptionHandler/BotExceptionHandler.java | 2 +- .../edu/java/bot/api/model/LinkUpdate.java | 6 -- .../configuration/RabbitMQConfiguration.java | 56 +++--------------- .../bot/configuration/configRecords/Bot.java | 4 -- .../{ => records}/ApplicationConfig.java | 7 ++- .../java/bot/configuration/records/Bot.java | 4 ++ .../{configRecords => records}/Scheduler.java | 2 +- .../bot/{firstBot => handler}/BotMain.java | 4 +- .../java/bot/{firstBot => handler}/DB.java | 2 +- .../{firstBot => handler}/MessageHandler.java | 4 +- .../bot/{firstBot => handler}/Updater.java | 2 +- .../{firstBot => handler}/commands/All.java | 2 +- .../{firstBot => handler}/commands/Help.java | 2 +- .../{firstBot => handler}/commands/List.java | 4 +- .../{firstBot => handler}/commands/Start.java | 2 +- .../{firstBot => handler}/commands/Track.java | 4 +- .../commands/Untrack.java | 4 +- .../bot/{api => }/model/ApiErrorResponse.java | 2 +- .../edu/java/bot/model/LinkUpdate.java | 6 ++ .../src/main/resources/application.properties | 2 +- FP/bot/src/main/resources/botapi.yml | 59 ------------------- FP/bot/src/test/java/BotTest.java | 4 +- FP/bot/target/classes/application.properties | 9 +++ FP/bot/target/consumer7370489798140565122pom | 0 FP/docker-compose.yml | 5 +- FP/scrapper/pom.xml | 6 ++ .../configuration/ApplicationConfig.java | 21 ++++++- .../configuration/RabbitMQConfiguration.java | 31 ++++------ .../rabbitmq/ScrapperQueueListener.java | 30 ---------- .../rabbitmq/ScrapperQueueProducer.java | 22 +++---- .../rabbitmq/SendNoticeServiceHttp.java | 11 ++++ .../rabbitmq/SendNoticeServiceImplement.java | 5 ++ .../rabbitmq/SendNoticeServiceQueue.java | 20 +++++++ .../src/main/resources/application.properties | 3 + 37 files changed, 150 insertions(+), 212 deletions(-) delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/LinkUpdate.java delete mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Bot.java rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/{ => records}/ApplicationConfig.java (72%) create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/Bot.java rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/{configRecords => records}/Scheduler.java (55%) rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{firstBot => handler}/BotMain.java (89%) rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{firstBot => handler}/DB.java (94%) rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{firstBot => handler}/MessageHandler.java (88%) rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{firstBot => handler}/Updater.java (97%) rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{firstBot => handler}/commands/All.java (76%) rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{firstBot => handler}/commands/Help.java (91%) rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{firstBot => handler}/commands/List.java (68%) rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{firstBot => handler}/commands/Start.java (69%) rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{firstBot => handler}/commands/Track.java (77%) rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{firstBot => handler}/commands/Untrack.java (78%) rename FP/bot/src/main/java/ru/tinkoff/edu/java/bot/{api => }/model/ApiErrorResponse.java (82%) create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/model/LinkUpdate.java delete mode 100644 FP/bot/src/main/resources/botapi.yml create mode 100644 FP/bot/target/classes/application.properties create mode 100644 FP/bot/target/consumer7370489798140565122pom delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceHttp.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceImplement.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceQueue.java diff --git a/FP/bot/pom.xml b/FP/bot/pom.xml index 60f49bd..3b3c9e6 100644 --- a/FP/bot/pom.xml +++ b/FP/bot/pom.xml @@ -22,7 +22,7 @@ org.springdoc springdoc-openapi-starter-webmvc-ui - 2.0.2 + 2.1.0 org.apache.commons @@ -84,5 +84,11 @@ maven-surefire-plugin 2.22.2 + + + org.springframework.boot + spring-boot-starter-amqp + 3.0.6 + \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java index 312857e..0bdeff0 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java @@ -3,8 +3,8 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import ru.tinkoff.edu.java.bot.configuration.ApplicationConfig; -import ru.tinkoff.edu.java.bot.firstBot.BotMain; +import ru.tinkoff.edu.java.bot.configuration.records.ApplicationConfig; +import ru.tinkoff.edu.java.bot.handler.BotMain; @SpringBootApplication @@ -14,7 +14,6 @@ public class BotApplication public static void main(String[] args){ var ctx = SpringApplication.run(BotApplication.class, args); ApplicationConfig config = ctx.getBean(ApplicationConfig.class); - BotMain bot = new BotMain(config.bot().token()); bot.start(); } diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/BotController.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/BotController.java index 25186cf..6a559cf 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/BotController.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/BotController.java @@ -1,7 +1,7 @@ package ru.tinkoff.edu.java.bot.api; import org.springframework.web.bind.annotation.*; -import ru.tinkoff.edu.java.bot.api.model.LinkUpdate; +import ru.tinkoff.edu.java.bot.model.LinkUpdate; @RestController @RequestMapping("/update") diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/exceptionHandler/BotExceptionHandler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/exceptionHandler/BotExceptionHandler.java index 732a56e..5beb1bd 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/exceptionHandler/BotExceptionHandler.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/exceptionHandler/BotExceptionHandler.java @@ -6,7 +6,7 @@ import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; -import ru.tinkoff.edu.java.bot.api.model.ApiErrorResponse; +import ru.tinkoff.edu.java.bot.model.ApiErrorResponse; @RestControllerAdvice public class BotExceptionHandler { diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/LinkUpdate.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/LinkUpdate.java deleted file mode 100644 index 0f44607..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/LinkUpdate.java +++ /dev/null @@ -1,6 +0,0 @@ -package ru.tinkoff.edu.java.bot.api.model; - -import java.util.List; - -public record LinkUpdate(long id, String url, String description, List tgChatIds) { -} \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java index b944fc5..86178a0 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java @@ -1,16 +1,11 @@ package ru.tinkoff.edu.java.bot.configuration; import org.springframework.amqp.core.*; -import org.springframework.amqp.support.converter.ClassMapper; -import org.springframework.amqp.support.converter.DefaultClassMapper; import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; import org.springframework.amqp.support.converter.MessageConverter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import ru.tinkoff.edu.java.bot.api.model.LinkUpdate; - -import java.util.HashMap; -import java.util.Map; +import ru.tinkoff.edu.java.bot.configuration.records.ApplicationConfig; @Configuration public class RabbitMQConfiguration { @@ -22,57 +17,22 @@ public RabbitMQConfiguration(ApplicationConfig config) { } @Bean - Queue queue() { - return QueueBuilder.durable(config.queueName()) - .withArgument("x-dead-letter-exchange", config.exchangeName()) - .withArgument("x-dead-letter-routing-key", config.routingKey() + ".dlq") - .build(); - } - - - @Bean - Queue deadLetterQueue() { - return new Queue(config.queueName() + ".dlq", true); + public DirectExchange exchange() { + return new DirectExchange(config.exchange()); } @Bean - DirectExchange exchange() { - return new DirectExchange(config.exchangeName()); + public Queue queue() { + return new Queue(config.queue()); } @Bean - Binding binding(Queue queue, DirectExchange exchange) { + public Binding binding(Queue queue, DirectExchange exchange) { return BindingBuilder.bind(queue).to(exchange).with(config.routingKey()); } @Bean - Binding dlqBinding(Queue deadLetterQueue, DirectExchange exchange) { - return BindingBuilder.bind(deadLetterQueue).to(exchange).with(config.routingKey() + ".dlq"); - } - - @Bean - public ClassMapper classMapper() { - Map> mappings = new HashMap<>(); - mappings.put("ru.tinkoff.edu.java.bot.api.model.LinkUpdate", LinkUpdate.class); - - DefaultClassMapper classMapper = new DefaultClassMapper(); - classMapper.setTrustedPackages("ru.tinkoff.edu.java.bot.api.model.*"); - classMapper.setIdClassMapping(mappings); - return classMapper; - } - - @Bean - public MessageConverter jsonMessageConverter(ClassMapper classMapper) { - Jackson2JsonMessageConverter jsonConverter = new Jackson2JsonMessageConverter(); - jsonConverter.setClassMapper(classMapper); - return jsonConverter; + public MessageConverter jsonMessageConverter() { + return new Jackson2JsonMessageConverter(); } - - - @Bean - public ScrapperQueueListener scrapperQueueListener(AmqpTemplate rabbitTemplate, UpdateService updateService) { - return new ScrapperQueueListener(rabbitTemplate, updateService); - } - - } \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Bot.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Bot.java deleted file mode 100644 index 37f4842..0000000 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Bot.java +++ /dev/null @@ -1,4 +0,0 @@ -package ru.tinkoff.edu.java.bot.configuration.configRecords; - -public record Bot(String token, String name) { -} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/ApplicationConfig.java similarity index 72% rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/ApplicationConfig.java index 49ce5e3..5ee81b6 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/ApplicationConfig.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/ApplicationConfig.java @@ -1,11 +1,9 @@ -package ru.tinkoff.edu.java.bot.configuration; +package ru.tinkoff.edu.java.bot.configuration.records; import jakarta.validation.constraints.NotNull; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.validation.annotation.Validated; -import ru.tinkoff.edu.java.bot.configuration.configRecords.Bot; -import ru.tinkoff.edu.java.bot.configuration.configRecords.Scheduler; @Validated @EnableScheduling @@ -13,6 +11,9 @@ public record ApplicationConfig( @NotNull String test, @NotNull Scheduler scheduler, + String exchange, + String routingKey, + String queue, Bot bot ) { } \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/Bot.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/Bot.java new file mode 100644 index 0000000..0a1fff4 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/Bot.java @@ -0,0 +1,4 @@ +package ru.tinkoff.edu.java.bot.configuration.records; + +public record Bot(String token, String name) { +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Scheduler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/Scheduler.java similarity index 55% rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Scheduler.java rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/Scheduler.java index 08278f6..daed115 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/configRecords/Scheduler.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/Scheduler.java @@ -1,4 +1,4 @@ -package ru.tinkoff.edu.java.bot.configuration.configRecords; +package ru.tinkoff.edu.java.bot.configuration.records; import java.time.Duration; diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/BotMain.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/BotMain.java similarity index 89% rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/BotMain.java rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/BotMain.java index f758472..33e72c8 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/BotMain.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/BotMain.java @@ -1,9 +1,9 @@ -package ru.tinkoff.edu.java.bot.firstBot; +package ru.tinkoff.edu.java.bot.handler; import com.pengrad.telegrambot.TelegramBot; import com.pengrad.telegrambot.request.SendMessage; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import ru.tinkoff.edu.java.bot.configuration.ApplicationConfig; +import ru.tinkoff.edu.java.bot.configuration.records.ApplicationConfig; @EnableConfigurationProperties(ApplicationConfig.class) diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/DB.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/DB.java similarity index 94% rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/DB.java rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/DB.java index 486a886..6b57338 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/DB.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/DB.java @@ -1,4 +1,4 @@ -package ru.tinkoff.edu.java.bot.firstBot; +package ru.tinkoff.edu.java.bot.handler; import java.util.ArrayList; diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/MessageHandler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/MessageHandler.java similarity index 88% rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/MessageHandler.java rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/MessageHandler.java index f003c84..56cfd57 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/MessageHandler.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/MessageHandler.java @@ -1,6 +1,6 @@ -package ru.tinkoff.edu.java.bot.firstBot; +package ru.tinkoff.edu.java.bot.handler; -import ru.tinkoff.edu.java.bot.firstBot.commands.All; +import ru.tinkoff.edu.java.bot.handler.commands.All; public class MessageHandler extends All { diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/Updater.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/Updater.java similarity index 97% rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/Updater.java rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/Updater.java index a01e4d9..746ad5e 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/Updater.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/Updater.java @@ -1,4 +1,4 @@ -package ru.tinkoff.edu.java.bot.firstBot; +package ru.tinkoff.edu.java.bot.handler; import com.pengrad.telegrambot.TelegramBot; import com.pengrad.telegrambot.UpdatesListener; diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/All.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/All.java similarity index 76% rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/All.java rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/All.java index 991b177..5f63723 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/All.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/All.java @@ -1,4 +1,4 @@ -package ru.tinkoff.edu.java.bot.firstBot.commands; +package ru.tinkoff.edu.java.bot.handler.commands; public class All implements List, Start, Track, Untrack, Help { protected String unknow() { diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Help.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Help.java similarity index 91% rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Help.java rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Help.java index 0761e05..4d0da5a 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Help.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Help.java @@ -1,4 +1,4 @@ -package ru.tinkoff.edu.java.bot.firstBot.commands; +package ru.tinkoff.edu.java.bot.handler.commands; public interface Help { default String help() { diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/List.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/List.java similarity index 68% rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/List.java rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/List.java index 8673887..fdadd4f 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/List.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/List.java @@ -1,6 +1,6 @@ -package ru.tinkoff.edu.java.bot.firstBot.commands; +package ru.tinkoff.edu.java.bot.handler.commands; -import ru.tinkoff.edu.java.bot.firstBot.DB; +import ru.tinkoff.edu.java.bot.handler.DB; public interface List { default String list() { diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Start.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Start.java similarity index 69% rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Start.java rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Start.java index d58c89c..5c4b5d7 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Start.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Start.java @@ -1,4 +1,4 @@ -package ru.tinkoff.edu.java.bot.firstBot.commands; +package ru.tinkoff.edu.java.bot.handler.commands; public interface Start { diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Track.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Track.java similarity index 77% rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Track.java rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Track.java index 0f4669e..fcd1042 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Track.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Track.java @@ -1,6 +1,6 @@ -package ru.tinkoff.edu.java.bot.firstBot.commands; +package ru.tinkoff.edu.java.bot.handler.commands; -import ru.tinkoff.edu.java.bot.firstBot.DB; +import ru.tinkoff.edu.java.bot.handler.DB; public interface Track { default String track(String link) { diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Untrack.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Untrack.java similarity index 78% rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Untrack.java rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Untrack.java index 6550daf..a196195 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/firstBot/commands/Untrack.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Untrack.java @@ -1,6 +1,6 @@ -package ru.tinkoff.edu.java.bot.firstBot.commands; +package ru.tinkoff.edu.java.bot.handler.commands; -import ru.tinkoff.edu.java.bot.firstBot.DB; +import ru.tinkoff.edu.java.bot.handler.DB; public interface Untrack { default String untrack(String link) { diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/ApiErrorResponse.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/model/ApiErrorResponse.java similarity index 82% rename from FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/ApiErrorResponse.java rename to FP/bot/src/main/java/ru/tinkoff/edu/java/bot/model/ApiErrorResponse.java index f43001e..57e1c06 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/api/model/ApiErrorResponse.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/model/ApiErrorResponse.java @@ -1,4 +1,4 @@ -package ru.tinkoff.edu.java.bot.api.model; +package ru.tinkoff.edu.java.bot.model; import java.util.List; diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/model/LinkUpdate.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/model/LinkUpdate.java new file mode 100644 index 0000000..d6b250b --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/model/LinkUpdate.java @@ -0,0 +1,6 @@ +package ru.tinkoff.edu.java.bot.model; + +import java.util.List; + +public record LinkUpdate(String url) { +} \ No newline at end of file diff --git a/FP/bot/src/main/resources/application.properties b/FP/bot/src/main/resources/application.properties index fedebeb..95d9a47 100644 --- a/FP/bot/src/main/resources/application.properties +++ b/FP/bot/src/main/resources/application.properties @@ -3,4 +3,4 @@ springdoc.swagger-ui.path=/swagger-ui app.scheduler.interval=50000 app.bot.token=5805337447:AAGnmh2isW2115L7tJWFojbpmSjNrarTvxQ app.bot.name=@SFRETbot -server.port=8081 +server.port=8081 \ No newline at end of file diff --git a/FP/bot/src/main/resources/botapi.yml b/FP/bot/src/main/resources/botapi.yml deleted file mode 100644 index 489441e..0000000 --- a/FP/bot/src/main/resources/botapi.yml +++ /dev/null @@ -1,59 +0,0 @@ -openapi: 3.0.1 -info: - title: Bot API - version: 1.0.0 - contact: - name: Alexander Biryukov - url: https://github.com -paths: - /updates: - post: - summary: Отправить обновление - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/LinkUpdate' - required: true - responses: - '200': - description: Обновление обработано - '400': - description: Некорректные параметры запроса - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorResponse' -components: - schemas: - ApiErrorResponse: - type: object - properties: - description: - type: string - code: - type: string - exceptionName: - type: string - exceptionMessage: - type: string - stacktrace: - type: array - items: - type: string - LinkUpdate: - type: object - properties: - id: - type: integer - format: int64 - url: - type: string - format: uri - description: - type: string - tgChatIds: - type: array - items: - type: integer - format: int64 diff --git a/FP/bot/src/test/java/BotTest.java b/FP/bot/src/test/java/BotTest.java index 1548bc9..4e14a70 100644 --- a/FP/bot/src/test/java/BotTest.java +++ b/FP/bot/src/test/java/BotTest.java @@ -1,7 +1,7 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import ru.tinkoff.edu.java.bot.firstBot.DB; -import ru.tinkoff.edu.java.bot.firstBot.MessageHandler; +import ru.tinkoff.edu.java.bot.handler.DB; +import ru.tinkoff.edu.java.bot.handler.MessageHandler; public class BotTest { diff --git a/FP/bot/target/classes/application.properties b/FP/bot/target/classes/application.properties new file mode 100644 index 0000000..6600aaa --- /dev/null +++ b/FP/bot/target/classes/application.properties @@ -0,0 +1,9 @@ +app.test=123 +springdoc.swagger-ui.path=/swagger-ui +app.scheduler.interval=50000 +app.bot.token=5805337447:AAGnmh2isW2115L7tJWFojbpmSjNrarTvxQ +app.bot.name=@SFRETbot +server.port=8081 +app.exchange=my-direct-exchange +app.queue=my-queue +app.routingKey=my-routing-key \ No newline at end of file diff --git a/FP/bot/target/consumer7370489798140565122pom b/FP/bot/target/consumer7370489798140565122pom new file mode 100644 index 0000000..e69de29 diff --git a/FP/docker-compose.yml b/FP/docker-compose.yml index b9f4994..3eeb07e 100644 --- a/FP/docker-compose.yml +++ b/FP/docker-compose.yml @@ -36,6 +36,7 @@ services: - ./migrations:/liquibase/changelog networks: - backend + rabbitmq: image: rabbitmq:3-management-alpine ports: @@ -44,8 +45,8 @@ services: volumes: - ./rabbitmq:/var/lib/rabbitmq environment: - - RABBITMQ_DEFAULT_USER=root - - RABBITMQ_DEFAULT_PASS=root + - RABBITMQ_DEFAULT_USER=guest + - RABBITMQ_DEFAULT_PASS=guest networks: backend: diff --git a/FP/scrapper/pom.xml b/FP/scrapper/pom.xml index bbd37fb..ff9b45a 100644 --- a/FP/scrapper/pom.xml +++ b/FP/scrapper/pom.xml @@ -112,5 +112,11 @@ maven-surefire-plugin 2.22.2 + + + org.springframework.boot + spring-boot-starter-amqp + 3.0.6 + \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java index 3a82d60..ec1a1e8 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java @@ -1,9 +1,15 @@ package ru.tinkoff.edu.java.scrapper.configuration; import jakarta.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.validation.annotation.Validated; +import ru.tinkoff.edu.java.scrapper.rabbitmq.ScrapperQueueProducer; +import ru.tinkoff.edu.java.scrapper.rabbitmq.SendNoticeServiceHttp; +import ru.tinkoff.edu.java.scrapper.rabbitmq.SendNoticeServiceImplement; +import ru.tinkoff.edu.java.scrapper.rabbitmq.SendNoticeServiceQueue; import ru.tinkoff.edu.java.scrapper.schedule.Scheduler; @Validated @@ -11,5 +17,16 @@ @EnableScheduling public record ApplicationConfig( @NotNull String test, - @NotNull Scheduler scheduler -) {} + @NotNull Scheduler scheduler, + @Value("${useQueue}") boolean useQueue +) { +@Bean +public SendNoticeServiceImplement notificationService(ScrapperQueueProducer queueProducer/*, BotClient botClient */) { + if (useQueue) { + return new SendNoticeServiceQueue(queueProducer); + } else { + /* Заглушка */ + return new SendNoticeServiceHttp(); + } +} +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java index b0d9449..40ffb29 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java @@ -1,17 +1,13 @@ package ru.tinkoff.edu.java.scrapper.configuration; import org.springframework.amqp.core.*; -import org.springframework.amqp.rabbit.connection.ConnectionFactory; -import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer; -import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter; import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; import org.springframework.amqp.support.converter.MessageConverter; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; -import ru.tinkoff.edu.java.scrapper.rabbitmq.ScrapperQueueProducer; +import org.springframework.context.annotation.Configuration; +import ru.tinkoff.edu.java.bot.configuration.records.ApplicationConfig; -@SpringBootApplication +@Configuration public class RabbitMQConfiguration { private final ApplicationConfig config; @@ -19,21 +15,19 @@ public class RabbitMQConfiguration { public RabbitMQConfiguration(ApplicationConfig config) { this.config = config; } + @Bean - Queue queue() { - return QueueBuilder.durable(config.queueName()) - .withArgument("x-dead-letter-exchange", config.exchangeName()) - .withArgument("x-dead-letter-routing-key", config.routingKey() + ".dlq") - .build(); + public DirectExchange exchange() { + return new DirectExchange(config.exchange()); } @Bean - DirectExchange exchange() { - return new DirectExchange(config.exchangeName()); + public Queue queue() { + return new Queue(config.queue()); } @Bean - Binding binding(Queue queue, DirectExchange exchange) { + public Binding binding(Queue queue, DirectExchange exchange) { return BindingBuilder.bind(queue).to(exchange).with(config.routingKey()); } @@ -41,9 +35,4 @@ Binding binding(Queue queue, DirectExchange exchange) { public MessageConverter jsonMessageConverter() { return new Jackson2JsonMessageConverter(); } - - @Bean - public ScrapperQueueProducer scrapperQueueProducer(AmqpTemplate rabbitTemplate) { - return new ScrapperQueueProducer(rabbitTemplate, config); - } -} +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java deleted file mode 100644 index 3507568..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java +++ /dev/null @@ -1,30 +0,0 @@ -import lombok.extern.slf4j.Slf4j; -import org.springframework.amqp.core.AmqpTemplate; -import org.springframework.amqp.rabbit.annotation.RabbitHandler; -import org.springframework.amqp.rabbit.annotation.RabbitListener; -import ru.tinkoff.edu.java.bot.dto.LinkUpdate; - -@RabbitListener(queues = "${app.queue-name}") -@Slf4j -public class ScrapperQueueListener { - - - private final AmqpTemplate rabbitTemplate; - - private final UpdateService updateService; - - - public ScrapperQueueListener(AmqpTemplate rabbitTemplate, UpdateService updateService) { - this.rabbitTemplate = rabbitTemplate; - this.updateService = updateService; - } - - @RabbitHandler - public void receiver(LinkUpdate update) { - log.info("Сообщение об обновлении получено: "+update); -// throw new RuntimeException("test exception"); - updateService.updateLink(update); - } - - -} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java index 84baa14..60990fd 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java @@ -1,27 +1,27 @@ package ru.tinkoff.edu.java.scrapper.rabbitmq; -import lombok.RequiredArgsConstructor; -import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.stereotype.Service; -import ru.tinkoff.edu.java.bot.api.model.LinkUpdate; - -import ru.tinkoff.edu.java.scrapper.configuration.ApplicationConfig; +import ru.tinkoff.edu.java.bot.configuration.RabbitMQConfiguration; +import ru.tinkoff.edu.java.bot.configuration.records.ApplicationConfig; +import ru.tinkoff.edu.java.bot.model.LinkUpdate; @Service public class ScrapperQueueProducer { - - private final AmqpTemplate rabbitTemplate; + private final RabbitTemplate rabbitTemplate; private final ApplicationConfig config; - - public ScrapperQueueProducer(AmqpTemplate rabbitTemplate, ApplicationConfig config) { + public ScrapperQueueProducer(RabbitTemplate rabbitTemplate, ApplicationConfig config) { this.rabbitTemplate = rabbitTemplate; this.config = config; } public void send(LinkUpdate update) { - rabbitTemplate.convertAndSend(config.exchangeName(), config.routingKey(), update); - System.out.println("Mess update: " + update); + String exchange = config.exchange(); // Имя обмена + String routingKey = config.routingKey(); // Маршрутный ключ + + rabbitTemplate.convertAndSend(exchange, routingKey, update); } } + diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceHttp.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceHttp.java new file mode 100644 index 0000000..7067329 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceHttp.java @@ -0,0 +1,11 @@ +package ru.tinkoff.edu.java.scrapper.rabbitmq; + +import org.springframework.stereotype.Service; + +@Service +public class SendNoticeServiceHttp implements SendNoticeServiceImplement { + @Override + public void sendNotice(String message) { + // TO DO WHERE CLIENT + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceImplement.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceImplement.java new file mode 100644 index 0000000..680f7fe --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceImplement.java @@ -0,0 +1,5 @@ +package ru.tinkoff.edu.java.scrapper.rabbitmq; + +public interface SendNoticeServiceImplement { + void sendNotice(String notice); +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceQueue.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceQueue.java new file mode 100644 index 0000000..c1ccbe3 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceQueue.java @@ -0,0 +1,20 @@ +package ru.tinkoff.edu.java.scrapper.rabbitmq; + +import org.springframework.stereotype.Service; +import ru.tinkoff.edu.java.bot.model.LinkUpdate; + +@Service +public class SendNoticeServiceQueue implements SendNoticeServiceImplement { + private final ScrapperQueueProducer queueProducer; + + public SendNoticeServiceQueue(ScrapperQueueProducer queueProducer) { + this.queueProducer = queueProducer; + } + + @Override + public void sendNotice(String message) { + // Отправка сообщения в очередь через ScrapperQueueProducer + LinkUpdate update = new LinkUpdate(message); + queueProducer.send(update); + } +} diff --git a/FP/scrapper/src/main/resources/application.properties b/FP/scrapper/src/main/resources/application.properties index 00d78d2..9bdcc75 100644 --- a/FP/scrapper/src/main/resources/application.properties +++ b/FP/scrapper/src/main/resources/application.properties @@ -3,3 +3,6 @@ springdoc.swagger-ui.path=/swagger-ui app.scheduler.interval=5000 git.link=https://github.com/Ray-Not/JavaGuava stack.link=https://stackoverflow.com/questions/1642028/what-is-the-operator-in-c +app.exchange=my-direct-exchange +app.queue=my-queue +app.routingKey=my-routing-key \ No newline at end of file From d086f8d834180439028a4732d788682411293475 Mon Sep 17 00:00:00 2001 From: Ray-Not <2sinsincuba@gmail.com> Date: Fri, 19 May 2023 05:44:05 +0500 Subject: [PATCH 6/9] =?UTF-8?q?=D0=92=D1=81=D0=B5=20=D1=80=D0=B5=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=BE,=20=D0=BD?= =?UTF-8?q?=D0=B5=D1=82=20=D0=B4=D0=BE=D1=81=D1=82=D1=83=D0=BF=D0=B0=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D0=BE=D1=87=D0=B5=D1=80=D0=B5=D0=B4=D0=B5?= =?UTF-8?q?=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../configuration/RabbitMQConfiguration.java | 26 ++- FP/bot/target/classes/application.properties | 5 +- FP/scrapper/pom.xml | 6 - .../java/scrapper/ScrapperApplication.java | 12 +- .../scrapper/api/ScrapperControllerLinks.java | 4 +- .../scrapper/api/model/AddLinkRequest.java | 3 - .../scrapper/api/model/UpdateService.java | 4 - .../configuration/ApplicationConfig.java | 7 +- .../configuration/RabbitMQConfiguration.java | 41 +++- .../java/scrapper/jdbc/JdbcLinkService.java | 6 +- .../scrapper/jdbc/mappers/ChatMapper.java | 2 +- .../scrapper/jdbc/mappers/LinkChatMapper.java | 2 +- .../scrapper/jdbc/mappers/LinkMapper.java | 2 +- .../jdbc/operations/LinkChatOperations.java | 2 +- .../jdbc/operations/LinkOperations.java | 6 +- .../java/scrapper/model/AddLinkRequest.java | 3 + .../{api => }/model/ChatResponse.java | 2 +- .../{api => }/model/LinkChatResponse.java | 2 +- .../{api => }/model/LinkResponse.java | 2 +- .../edu/java/scrapper/model/LinkUpdate.java | 4 + .../{api => }/model/ListLinksResponse.java | 2 +- .../{api => }/model/RemoveLinkRequest.java | 2 +- .../java/scrapper/model/UpdateService.java | 4 + .../HandleNoticeServiceImplement.java | 5 + .../rabbitmq/HandleNoticeServiceQueue.java | 16 ++ .../rabbitmq/ScrapperQueueListener.java | 19 ++ .../rabbitmq/ScrapperQueueProducer.java | 9 +- .../rabbitmq/SendNoticeServiceQueue.java | 2 +- .../schedule/LinkUpdaterScheduler.java | 84 ++++---- .../src/main/resources/application.properties | 3 +- .../target/classes/application.properties | 9 + FP/scrapper/target/classes/scrapperapi.yml | 184 ++++++++++++++++++ 32 files changed, 388 insertions(+), 92 deletions(-) delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/AddLinkRequest.java delete mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/UpdateService.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/AddLinkRequest.java rename FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/{api => }/model/ChatResponse.java (52%) rename FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/{api => }/model/LinkChatResponse.java (55%) rename FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/{api => }/model/LinkResponse.java (51%) create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkUpdate.java rename FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/{api => }/model/ListLinksResponse.java (66%) rename FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/{api => }/model/RemoveLinkRequest.java (50%) create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/UpdateService.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/HandleNoticeServiceImplement.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/HandleNoticeServiceQueue.java create mode 100644 FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java create mode 100644 FP/scrapper/target/classes/application.properties create mode 100644 FP/scrapper/target/classes/scrapperapi.yml diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java index 86178a0..1616669 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/RabbitMQConfiguration.java @@ -7,6 +7,8 @@ import org.springframework.context.annotation.Configuration; import ru.tinkoff.edu.java.bot.configuration.records.ApplicationConfig; +import java.util.Collections; + @Configuration public class RabbitMQConfiguration { @@ -23,16 +25,32 @@ public DirectExchange exchange() { @Bean public Queue queue() { - return new Queue(config.queue()); + return QueueBuilder.durable(config.queue()) + .withArgument("x-dead-letter-exchange",config.queue() + ".dlq") + .build(); } @Bean public Binding binding(Queue queue, DirectExchange exchange) { - return BindingBuilder.bind(queue).to(exchange).with(config.routingKey()); + return BindingBuilder.bind(queue) + .to(exchange) + .with(config.routingKey()); + } + + @Bean + public DirectExchange dlqExchange() { + return new DirectExchange(config.exchange() + ".dlq"); + } + + @Bean + public Queue dlqQueue() { + return QueueBuilder.durable(config.queue() + ".dlq").build(); } @Bean - public MessageConverter jsonMessageConverter() { - return new Jackson2JsonMessageConverter(); + public Binding dlqBinding() { + return BindingBuilder.bind(dlqQueue()) + .to(dlqExchange()) + .with(config.routingKey()); } } \ No newline at end of file diff --git a/FP/bot/target/classes/application.properties b/FP/bot/target/classes/application.properties index 6600aaa..95d9a47 100644 --- a/FP/bot/target/classes/application.properties +++ b/FP/bot/target/classes/application.properties @@ -3,7 +3,4 @@ springdoc.swagger-ui.path=/swagger-ui app.scheduler.interval=50000 app.bot.token=5805337447:AAGnmh2isW2115L7tJWFojbpmSjNrarTvxQ app.bot.name=@SFRETbot -server.port=8081 -app.exchange=my-direct-exchange -app.queue=my-queue -app.routingKey=my-routing-key \ No newline at end of file +server.port=8081 \ No newline at end of file diff --git a/FP/scrapper/pom.xml b/FP/scrapper/pom.xml index ff9b45a..fad5590 100644 --- a/FP/scrapper/pom.xml +++ b/FP/scrapper/pom.xml @@ -71,12 +71,6 @@ 3.0.5 - - org.example - bot - 1.0 - compile - org.testcontainers junit-jupiter diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java index 959ba70..c2e1b98 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java @@ -1,12 +1,15 @@ package ru.tinkoff.edu.java.scrapper; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import ru.tinkoff.edu.java.scrapper.client.ClientConfiguration; import ru.tinkoff.edu.java.scrapper.configuration.ApplicationConfig; +import ru.tinkoff.edu.java.scrapper.rabbitmq.ScrapperQueueProducer; +import ru.tinkoff.edu.java.scrapper.rabbitmq.SendNoticeServiceQueue; @SpringBootApplication @EnableConfigurationProperties(ApplicationConfig.class) @@ -16,6 +19,11 @@ public class ScrapperApplication { public static void main(String[] args) { var ctx = SpringApplication.run(ScrapperApplication.class, args); ApplicationConfig config = ctx.getBean(ApplicationConfig.class); - System.out.println("----------------------------------------------------------------"); + System.out.println("----------------------------------------------------------------" + config); + SendNoticeServiceQueue notificationService = new SendNoticeServiceQueue(new ScrapperQueueProducer( + new RabbitTemplate(), + config + )); + notificationService.sendNotice("Вот-вот"); } } diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerLinks.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerLinks.java index c4ad690..47540df 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerLinks.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/ScrapperControllerLinks.java @@ -5,8 +5,10 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import ru.tinkoff.edu.java.scrapper.api.model.*; import ru.tinkoff.edu.java.scrapper.jdbc.JdbcLinkService; +import ru.tinkoff.edu.java.scrapper.model.AddLinkRequest; +import ru.tinkoff.edu.java.scrapper.model.LinkResponse; +import ru.tinkoff.edu.java.scrapper.model.RemoveLinkRequest; import java.util.List; diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/AddLinkRequest.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/AddLinkRequest.java deleted file mode 100644 index 7282291..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/AddLinkRequest.java +++ /dev/null @@ -1,3 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.api.model; - -public record AddLinkRequest(String link) {} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/UpdateService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/UpdateService.java deleted file mode 100644 index 006d0b0..0000000 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/UpdateService.java +++ /dev/null @@ -1,4 +0,0 @@ -package ru.tinkoff.edu.java.scrapper.api.model; - -public class UpdateService { -} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java index ec1a1e8..52af096 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java @@ -1,9 +1,11 @@ package ru.tinkoff.edu.java.scrapper.configuration; import jakarta.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.validation.annotation.Validated; import ru.tinkoff.edu.java.scrapper.rabbitmq.ScrapperQueueProducer; @@ -18,7 +20,10 @@ public record ApplicationConfig( @NotNull String test, @NotNull Scheduler scheduler, - @Value("${useQueue}") boolean useQueue + Boolean useQueue, + String exchange, + String routingKey, + String queue ) { @Bean public SendNoticeServiceImplement notificationService(ScrapperQueueProducer queueProducer/*, BotClient botClient */) { diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java index 40ffb29..f89b8b8 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java @@ -1,11 +1,19 @@ package ru.tinkoff.edu.java.scrapper.configuration; +import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBean; import org.springframework.amqp.core.*; +import org.springframework.amqp.support.converter.ClassMapper; +import org.springframework.amqp.support.converter.DefaultClassMapper; import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; import org.springframework.amqp.support.converter.MessageConverter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import ru.tinkoff.edu.java.bot.configuration.records.ApplicationConfig; +import ru.tinkoff.edu.java.scrapper.model.LinkUpdate; + +import java.util.HashMap; +import java.util.Map; @Configuration public class RabbitMQConfiguration { @@ -23,7 +31,9 @@ public DirectExchange exchange() { @Bean public Queue queue() { - return new Queue(config.queue()); + return QueueBuilder.durable(config.queue()) + .withArgument("x-dead-letter-exchange", config.queue() + ".dlq") + .build(); } @Bean @@ -32,7 +42,30 @@ public Binding binding(Queue queue, DirectExchange exchange) { } @Bean - public MessageConverter jsonMessageConverter() { - return new Jackson2JsonMessageConverter(); + public ClassMapper classMapper(){ + Map> mappings = new HashMap<>(); + mappings.put("ru.tinkoff.edu.java.scrapper.model.LinkUpdate", LinkUpdate.class); + + DefaultClassMapper classMapper = new DefaultClassMapper(); + classMapper.setTrustedPackages("ru.tinkoff.edu.java.scrapper.model.*"); + classMapper.setIdClassMapping(mappings); + return classMapper; + } + + @Bean + public MessageConverter jsonMessageConverter(ClassMapper classMapper){ + Jackson2JsonMessageConverter jsonConverter=new Jackson2JsonMessageConverter(); + jsonConverter.setClassMapper(classMapper); + return jsonConverter; + } + + @Bean + public ConnectionFactory connectionFactory() { + CachingConnectionFactory connectionFactory = new CachingConnectionFactory("0.0.0.0", 5672); + connectionFactory.setUsername("guest"); + connectionFactory.setPassword("guest"); + // Другие настройки, если необходимо + + return connectionFactory; } } \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java index 6eb52b5..380ca48 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java @@ -3,9 +3,9 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.web.reactive.function.client.WebClientResponseException; import ru.tinkoff.edu.java.linkparser.LinkParser; -import ru.tinkoff.edu.java.scrapper.api.model.AddLinkRequest; -import ru.tinkoff.edu.java.scrapper.api.model.LinkResponse; -import ru.tinkoff.edu.java.scrapper.api.model.RemoveLinkRequest; +import ru.tinkoff.edu.java.scrapper.model.AddLinkRequest; +import ru.tinkoff.edu.java.scrapper.model.LinkResponse; +import ru.tinkoff.edu.java.scrapper.model.RemoveLinkRequest; import ru.tinkoff.edu.java.scrapper.client.ClientConfiguration; import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.*; import ru.tinkoff.edu.java.scrapper.jdbc.operations.ChatOperations; diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/ChatMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/ChatMapper.java index b979f13..026139a 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/ChatMapper.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/ChatMapper.java @@ -1,7 +1,7 @@ package ru.tinkoff.edu.java.scrapper.jdbc.mappers; import org.springframework.jdbc.core.RowMapper; -import ru.tinkoff.edu.java.scrapper.api.model.ChatResponse; +import ru.tinkoff.edu.java.scrapper.model.ChatResponse; import java.sql.ResultSet; import java.sql.SQLException; diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkChatMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkChatMapper.java index e9e98e7..4b52ef9 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkChatMapper.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkChatMapper.java @@ -1,7 +1,7 @@ package ru.tinkoff.edu.java.scrapper.jdbc.mappers; import org.springframework.jdbc.core.RowMapper; -import ru.tinkoff.edu.java.scrapper.api.model.LinkChatResponse; +import ru.tinkoff.edu.java.scrapper.model.LinkChatResponse; import java.sql.ResultSet; import java.sql.SQLException; diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkMapper.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkMapper.java index ac50329..914d113 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkMapper.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/mappers/LinkMapper.java @@ -2,7 +2,7 @@ import org.springframework.jdbc.core.RowMapper; -import ru.tinkoff.edu.java.scrapper.api.model.LinkResponse; +import ru.tinkoff.edu.java.scrapper.model.LinkResponse; import java.sql.ResultSet; import java.sql.SQLException; diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkChatOperations.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkChatOperations.java index 29cfe7d..e40b248 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkChatOperations.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkChatOperations.java @@ -1,7 +1,7 @@ package ru.tinkoff.edu.java.scrapper.jdbc.operations; import org.springframework.jdbc.core.JdbcTemplate; -import ru.tinkoff.edu.java.scrapper.api.model.LinkChatResponse; +import ru.tinkoff.edu.java.scrapper.model.LinkChatResponse; import ru.tinkoff.edu.java.scrapper.jdbc.mappers.LinkChatMapper; import java.util.List; diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java index ad282fe..7907633 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java @@ -1,9 +1,9 @@ package ru.tinkoff.edu.java.scrapper.jdbc.operations; import org.springframework.jdbc.core.JdbcTemplate; -import ru.tinkoff.edu.java.scrapper.api.model.AddLinkRequest; -import ru.tinkoff.edu.java.scrapper.api.model.LinkResponse; -import ru.tinkoff.edu.java.scrapper.api.model.RemoveLinkRequest; +import ru.tinkoff.edu.java.scrapper.model.AddLinkRequest; +import ru.tinkoff.edu.java.scrapper.model.LinkResponse; +import ru.tinkoff.edu.java.scrapper.model.RemoveLinkRequest; import ru.tinkoff.edu.java.scrapper.jdbc.mappers.LinkMapper; import java.util.ArrayList; diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/AddLinkRequest.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/AddLinkRequest.java new file mode 100644 index 0000000..e7f8aa4 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/AddLinkRequest.java @@ -0,0 +1,3 @@ +package ru.tinkoff.edu.java.scrapper.model; + +public record AddLinkRequest(String link) {} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ChatResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/ChatResponse.java similarity index 52% rename from FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ChatResponse.java rename to FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/ChatResponse.java index eb09922..d1e1893 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ChatResponse.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/ChatResponse.java @@ -1,3 +1,3 @@ -package ru.tinkoff.edu.java.scrapper.api.model; +package ru.tinkoff.edu.java.scrapper.model; public record ChatResponse(long chat_id, int id) {} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkChatResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkChatResponse.java similarity index 55% rename from FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkChatResponse.java rename to FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkChatResponse.java index 1f62147..6ef6a2c 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkChatResponse.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkChatResponse.java @@ -1,3 +1,3 @@ -package ru.tinkoff.edu.java.scrapper.api.model; +package ru.tinkoff.edu.java.scrapper.model; public record LinkChatResponse(int linkid, int chatid) {} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkResponse.java similarity index 51% rename from FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkResponse.java rename to FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkResponse.java index 023172d..d5192ab 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/LinkResponse.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkResponse.java @@ -1,3 +1,3 @@ -package ru.tinkoff.edu.java.scrapper.api.model; +package ru.tinkoff.edu.java.scrapper.model; public record LinkResponse(String url, int id) {} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkUpdate.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkUpdate.java new file mode 100644 index 0000000..ba13a15 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/LinkUpdate.java @@ -0,0 +1,4 @@ +package ru.tinkoff.edu.java.scrapper.model; + +public record LinkUpdate(String url) { +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ListLinksResponse.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/ListLinksResponse.java similarity index 66% rename from FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ListLinksResponse.java rename to FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/ListLinksResponse.java index 9c9ed5b..6a04698 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/ListLinksResponse.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/ListLinksResponse.java @@ -1,4 +1,4 @@ -package ru.tinkoff.edu.java.scrapper.api.model; +package ru.tinkoff.edu.java.scrapper.model; import java.util.*; diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/RemoveLinkRequest.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/RemoveLinkRequest.java similarity index 50% rename from FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/RemoveLinkRequest.java rename to FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/RemoveLinkRequest.java index 3e2a8f0..1f9b6ee 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/api/model/RemoveLinkRequest.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/RemoveLinkRequest.java @@ -1,3 +1,3 @@ -package ru.tinkoff.edu.java.scrapper.api.model; +package ru.tinkoff.edu.java.scrapper.model; public record RemoveLinkRequest(String link) {} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/UpdateService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/UpdateService.java new file mode 100644 index 0000000..4d53819 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/model/UpdateService.java @@ -0,0 +1,4 @@ +package ru.tinkoff.edu.java.scrapper.model; + +public class UpdateService { +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/HandleNoticeServiceImplement.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/HandleNoticeServiceImplement.java new file mode 100644 index 0000000..8432dad --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/HandleNoticeServiceImplement.java @@ -0,0 +1,5 @@ +package ru.tinkoff.edu.java.scrapper.rabbitmq; + +public interface HandleNoticeServiceImplement { + void handleNotification(String message); +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/HandleNoticeServiceQueue.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/HandleNoticeServiceQueue.java new file mode 100644 index 0000000..deb53c3 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/HandleNoticeServiceQueue.java @@ -0,0 +1,16 @@ +package ru.tinkoff.edu.java.scrapper.rabbitmq; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +@Service +public class HandleNoticeServiceQueue implements HandleNoticeServiceImplement { + + Logger log = LoggerFactory.getLogger(HandleNoticeServiceQueue.class); + @Override + public void handleNotification(String message) { + log.info("Пришло уведомление с Rabbit очереди: " + message); + } +} \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java new file mode 100644 index 0000000..1d587b6 --- /dev/null +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueListener.java @@ -0,0 +1,19 @@ +package ru.tinkoff.edu.java.scrapper.rabbitmq; + +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import ru.tinkoff.edu.java.scrapper.model.LinkUpdate; + +@RabbitListener(queues = "${app.queue}") +public class ScrapperQueueListener { + private final HandleNoticeServiceQueue handleNoticeServiceQueue; + + public ScrapperQueueListener(HandleNoticeServiceQueue notificationHandler) { + this.handleNoticeServiceQueue = notificationHandler; + } + + @RabbitHandler + public void receiver(LinkUpdate update) { + handleNoticeServiceQueue.handleNotification(update.url()); + } +} diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java index 60990fd..c592025 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/ScrapperQueueProducer.java @@ -1,12 +1,13 @@ package ru.tinkoff.edu.java.scrapper.rabbitmq; import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import ru.tinkoff.edu.java.bot.configuration.RabbitMQConfiguration; -import ru.tinkoff.edu.java.bot.configuration.records.ApplicationConfig; -import ru.tinkoff.edu.java.bot.model.LinkUpdate; +import ru.tinkoff.edu.java.scrapper.configuration.ApplicationConfig; +import ru.tinkoff.edu.java.scrapper.model.LinkUpdate; @Service + public class ScrapperQueueProducer { private final RabbitTemplate rabbitTemplate; @@ -21,7 +22,7 @@ public void send(LinkUpdate update) { String exchange = config.exchange(); // Имя обмена String routingKey = config.routingKey(); // Маршрутный ключ - rabbitTemplate.convertAndSend(exchange, routingKey, update); + rabbitTemplate.convertAndSend(exchange, routingKey, update.url()); } } diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceQueue.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceQueue.java index c1ccbe3..70eed14 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceQueue.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/rabbitmq/SendNoticeServiceQueue.java @@ -1,7 +1,7 @@ package ru.tinkoff.edu.java.scrapper.rabbitmq; import org.springframework.stereotype.Service; -import ru.tinkoff.edu.java.bot.model.LinkUpdate; +import ru.tinkoff.edu.java.scrapper.model.LinkUpdate; @Service public class SendNoticeServiceQueue implements SendNoticeServiceImplement { diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdaterScheduler.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdaterScheduler.java index 10c9caa..63acc43 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdaterScheduler.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/schedule/LinkUpdaterScheduler.java @@ -18,46 +18,46 @@ @Service public class LinkUpdaterScheduler implements LinkOperations { - private final static Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); - - private final JdbcTemplate jdbcTemplate; - ArrayList link_list = new ArrayList<>(); - static int ix = 0; - ClientConfiguration client = new ClientConfiguration(); - LinkParser pars = new LinkParser(); - boolean git_link_is_activity; - boolean stack_link_is_activity; - - public LinkUpdaterScheduler(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - @Scheduled(fixedDelayString = "${app.scheduler.interval}") - public void update() { - int i; - for (i = 0; i < i_getAllIds(jdbcTemplate).size(); i++){ - if (!link_list.contains(i_getAllIds(jdbcTemplate).get(i).url())) { - link_list.add(i_getAllIds(jdbcTemplate).get(i).url()); - } - } - try { - client.gitHubClient(pars.getLink(link_list.get(ix))); - git_link_is_activity = true; - } catch (WebClientResponseException e) { - git_link_is_activity = false; - } - try { - client.stackOverflowClient(pars.getLink(link_list.get(ix))); - stack_link_is_activity = true; - } catch (WebClientResponseException ignored) { - stack_link_is_activity = false; - } - if (!(git_link_is_activity || stack_link_is_activity)) { - String link = "Ссылка %s устарела"; - link = link.formatted(i_getAllIds(jdbcTemplate).get(ix).url()); - LOGGER.log(Level.INFO, link); - } - ix++; - if (ix == link_list.size()) ix = 0; - } +// private final static Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); +// +// private final JdbcTemplate jdbcTemplate; +// ArrayList link_list = new ArrayList<>(); +// static int ix = 0; +// ClientConfiguration client = new ClientConfiguration(); +// LinkParser pars = new LinkParser(); +// boolean git_link_is_activity; +// boolean stack_link_is_activity; +// +// public LinkUpdaterScheduler(JdbcTemplate jdbcTemplate) { +// this.jdbcTemplate = jdbcTemplate; +// } +// +// @Scheduled(fixedDelayString = "${app.scheduler.interval}") +// public void update() { +// int i; +// for (i = 0; i < i_getAllIds(jdbcTemplate).size(); i++){ +// if (!link_list.contains(i_getAllIds(jdbcTemplate).get(i).url())) { +// link_list.add(i_getAllIds(jdbcTemplate).get(i).url()); +// } +// } +// try { +// client.gitHubClient(pars.getLink(link_list.get(ix))); +// git_link_is_activity = true; +// } catch (WebClientResponseException e) { +// git_link_is_activity = false; +// } +// try { +// client.stackOverflowClient(pars.getLink(link_list.get(ix))); +// stack_link_is_activity = true; +// } catch (WebClientResponseException ignored) { +// stack_link_is_activity = false; +// } +// if (!(git_link_is_activity || stack_link_is_activity)) { +// String link = "Ссылка %s устарела"; +// link = link.formatted(i_getAllIds(jdbcTemplate).get(ix).url()); +// LOGGER.log(Level.INFO, link); +// } +// ix++; +// if (ix == link_list.size()) ix = 0; +// } } diff --git a/FP/scrapper/src/main/resources/application.properties b/FP/scrapper/src/main/resources/application.properties index 9bdcc75..d4267e9 100644 --- a/FP/scrapper/src/main/resources/application.properties +++ b/FP/scrapper/src/main/resources/application.properties @@ -5,4 +5,5 @@ git.link=https://github.com/Ray-Not/JavaGuava stack.link=https://stackoverflow.com/questions/1642028/what-is-the-operator-in-c app.exchange=my-direct-exchange app.queue=my-queue -app.routingKey=my-routing-key \ No newline at end of file +app.routingKey=my-routing-key +app.useQueue=True \ No newline at end of file diff --git a/FP/scrapper/target/classes/application.properties b/FP/scrapper/target/classes/application.properties new file mode 100644 index 0000000..d4267e9 --- /dev/null +++ b/FP/scrapper/target/classes/application.properties @@ -0,0 +1,9 @@ +app.test=123 +springdoc.swagger-ui.path=/swagger-ui +app.scheduler.interval=5000 +git.link=https://github.com/Ray-Not/JavaGuava +stack.link=https://stackoverflow.com/questions/1642028/what-is-the-operator-in-c +app.exchange=my-direct-exchange +app.queue=my-queue +app.routingKey=my-routing-key +app.useQueue=True \ No newline at end of file diff --git a/FP/scrapper/target/classes/scrapperapi.yml b/FP/scrapper/target/classes/scrapperapi.yml new file mode 100644 index 0000000..c98cf7d --- /dev/null +++ b/FP/scrapper/target/classes/scrapperapi.yml @@ -0,0 +1,184 @@ +openapi: 3.0.1 +info: + title: Scrapper API + version: 1.0.0 + contact: + name: Alexander Biryukov + url: https://github.com +paths: + /tg-chat/{id}: + post: + summary: Зарегистрировать чат + parameters: + - name: id + in: path + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: Чат зарегистрирован + '400': + description: Некорректные параметры запроса + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorResponse' + delete: + summary: Удалить чат + parameters: + - name: id + in: path + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: Чат успешно удалён + '400': + description: Некорректные параметры запроса + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorResponse' + '404': + description: Чат не существует + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorResponse' + /links: + get: + summary: Получить все отслеживаемые ссылки + parameters: + - name: Tg-Chat-Id + in: header + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: Ссылки успешно получены + content: + application/json: + schema: + $ref: '#/components/schemas/ListLinksResponse' + '400': + description: Некорректные параметры запроса + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorResponse' + post: + summary: Добавить отслеживание ссылки + parameters: + - name: Tg-Chat-Id + in: header + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AddLinkRequest' + required: true + responses: + '200': + description: Ссылка успешно добавлена + content: + application/json: + schema: + $ref: '#/components/schemas/LinkResponse' + '400': + description: Некорректные параметры запроса + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorResponse' + delete: + summary: Убрать отслеживание ссылки + parameters: + - name: Tg-Chat-Id + in: header + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RemoveLinkRequest' + required: true + responses: + '200': + description: Ссылка успешно убрана + content: + application/json: + schema: + $ref: '#/components/schemas/LinkResponse' + '400': + description: Некорректные параметры запроса + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorResponse' + '404': + description: Ссылка не найдена + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorResponse' +components: + schemas: + LinkResponse: + type: object + properties: + id: + type: integer + format: int64 + url: + type: string + format: uri + ApiErrorResponse: + type: object + properties: + description: + type: string + code: + type: string + exceptionName: + type: string + exceptionMessage: + type: string + stacktrace: + type: array + items: + type: string + AddLinkRequest: + type: object + properties: + link: + type: string + format: uri + ListLinksResponse: + type: object + properties: + links: + type: array + items: + $ref: '#/components/schemas/LinkResponse' + size: + type: integer + format: int32 + RemoveLinkRequest: + type: object + properties: + link: + type: string + format: uri From 86e51d7ba653c8fede6ab23199dacb668b238c17 Mon Sep 17 00:00:00 2001 From: Ray-Not <2sinsincuba@gmail.com> Date: Fri, 19 May 2023 16:50:01 +0500 Subject: [PATCH 7/9] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=BD?= =?UTF-8?q?=D0=BE=D0=B3=D0=BE=20=D0=BA=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=D0=B0?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D0=91=D0=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- FP/bot/target/classes/application.properties | 6 - FP/bot/target/consumer7370489798140565122pom | 0 FP/docker-compose.yml | 1 + FP/migrations/chats_links_scheme.sql | 8 + FP/migrations/master.xml | 11 ++ .../configuration/RabbitMQConfiguration.java | 2 +- .../src/main/resources/scrapperapi.yml | 184 ------------------ .../target/classes/application.properties | 9 - FP/scrapper/target/classes/scrapperapi.yml | 184 ------------------ 10 files changed, 22 insertions(+), 385 deletions(-) delete mode 100644 FP/bot/target/classes/application.properties delete mode 100644 FP/bot/target/consumer7370489798140565122pom create mode 100644 FP/migrations/chats_links_scheme.sql create mode 100644 FP/migrations/master.xml delete mode 100644 FP/scrapper/src/main/resources/scrapperapi.yml delete mode 100644 FP/scrapper/target/classes/application.properties delete mode 100644 FP/scrapper/target/classes/scrapperapi.yml diff --git a/.gitignore b/.gitignore index d457c3c..f87b265 100644 --- a/.gitignore +++ b/.gitignore @@ -27,5 +27,5 @@ hs_err_pid* FP/.idea/ # volumes -FP/migrations/ +FP/migrations/postgres_data/ FP/rabbitmq/ \ No newline at end of file diff --git a/FP/bot/target/classes/application.properties b/FP/bot/target/classes/application.properties deleted file mode 100644 index 95d9a47..0000000 --- a/FP/bot/target/classes/application.properties +++ /dev/null @@ -1,6 +0,0 @@ -app.test=123 -springdoc.swagger-ui.path=/swagger-ui -app.scheduler.interval=50000 -app.bot.token=5805337447:AAGnmh2isW2115L7tJWFojbpmSjNrarTvxQ -app.bot.name=@SFRETbot -server.port=8081 \ No newline at end of file diff --git a/FP/bot/target/consumer7370489798140565122pom b/FP/bot/target/consumer7370489798140565122pom deleted file mode 100644 index e69de29..0000000 diff --git a/FP/docker-compose.yml b/FP/docker-compose.yml index 3eeb07e..1d76d36 100644 --- a/FP/docker-compose.yml +++ b/FP/docker-compose.yml @@ -39,6 +39,7 @@ services: rabbitmq: image: rabbitmq:3-management-alpine + container_name: rabbitmq ports: - 5672:5672 # Порт для AMQP - 15672:15672 # Порт для RabbitMQ Management UI diff --git a/FP/migrations/chats_links_scheme.sql b/FP/migrations/chats_links_scheme.sql new file mode 100644 index 0000000..63882e8 --- /dev/null +++ b/FP/migrations/chats_links_scheme.sql @@ -0,0 +1,8 @@ +CREATE TABLE links (id INTEGER, link VARCHAR(128) NOT NULL); + +CREATE TABLE tgChats (id INTEGER, tg_chat_id BIGINT NOT NULL); + +CREATE TABLE links_tgChats ( + linkid INTEGER, + chatid INTEGER +); \ No newline at end of file diff --git a/FP/migrations/master.xml b/FP/migrations/master.xml new file mode 100644 index 0000000..5d643de --- /dev/null +++ b/FP/migrations/master.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java index f89b8b8..8682387 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java @@ -61,7 +61,7 @@ public MessageConverter jsonMessageConverter(ClassMapper classMapper){ @Bean public ConnectionFactory connectionFactory() { - CachingConnectionFactory connectionFactory = new CachingConnectionFactory("0.0.0.0", 5672); + CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost", 5672); connectionFactory.setUsername("guest"); connectionFactory.setPassword("guest"); // Другие настройки, если необходимо diff --git a/FP/scrapper/src/main/resources/scrapperapi.yml b/FP/scrapper/src/main/resources/scrapperapi.yml deleted file mode 100644 index c98cf7d..0000000 --- a/FP/scrapper/src/main/resources/scrapperapi.yml +++ /dev/null @@ -1,184 +0,0 @@ -openapi: 3.0.1 -info: - title: Scrapper API - version: 1.0.0 - contact: - name: Alexander Biryukov - url: https://github.com -paths: - /tg-chat/{id}: - post: - summary: Зарегистрировать чат - parameters: - - name: id - in: path - required: true - schema: - type: integer - format: int64 - responses: - '200': - description: Чат зарегистрирован - '400': - description: Некорректные параметры запроса - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorResponse' - delete: - summary: Удалить чат - parameters: - - name: id - in: path - required: true - schema: - type: integer - format: int64 - responses: - '200': - description: Чат успешно удалён - '400': - description: Некорректные параметры запроса - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorResponse' - '404': - description: Чат не существует - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorResponse' - /links: - get: - summary: Получить все отслеживаемые ссылки - parameters: - - name: Tg-Chat-Id - in: header - required: true - schema: - type: integer - format: int64 - responses: - '200': - description: Ссылки успешно получены - content: - application/json: - schema: - $ref: '#/components/schemas/ListLinksResponse' - '400': - description: Некорректные параметры запроса - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorResponse' - post: - summary: Добавить отслеживание ссылки - parameters: - - name: Tg-Chat-Id - in: header - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/AddLinkRequest' - required: true - responses: - '200': - description: Ссылка успешно добавлена - content: - application/json: - schema: - $ref: '#/components/schemas/LinkResponse' - '400': - description: Некорректные параметры запроса - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorResponse' - delete: - summary: Убрать отслеживание ссылки - parameters: - - name: Tg-Chat-Id - in: header - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/RemoveLinkRequest' - required: true - responses: - '200': - description: Ссылка успешно убрана - content: - application/json: - schema: - $ref: '#/components/schemas/LinkResponse' - '400': - description: Некорректные параметры запроса - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorResponse' - '404': - description: Ссылка не найдена - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorResponse' -components: - schemas: - LinkResponse: - type: object - properties: - id: - type: integer - format: int64 - url: - type: string - format: uri - ApiErrorResponse: - type: object - properties: - description: - type: string - code: - type: string - exceptionName: - type: string - exceptionMessage: - type: string - stacktrace: - type: array - items: - type: string - AddLinkRequest: - type: object - properties: - link: - type: string - format: uri - ListLinksResponse: - type: object - properties: - links: - type: array - items: - $ref: '#/components/schemas/LinkResponse' - size: - type: integer - format: int32 - RemoveLinkRequest: - type: object - properties: - link: - type: string - format: uri diff --git a/FP/scrapper/target/classes/application.properties b/FP/scrapper/target/classes/application.properties deleted file mode 100644 index d4267e9..0000000 --- a/FP/scrapper/target/classes/application.properties +++ /dev/null @@ -1,9 +0,0 @@ -app.test=123 -springdoc.swagger-ui.path=/swagger-ui -app.scheduler.interval=5000 -git.link=https://github.com/Ray-Not/JavaGuava -stack.link=https://stackoverflow.com/questions/1642028/what-is-the-operator-in-c -app.exchange=my-direct-exchange -app.queue=my-queue -app.routingKey=my-routing-key -app.useQueue=True \ No newline at end of file diff --git a/FP/scrapper/target/classes/scrapperapi.yml b/FP/scrapper/target/classes/scrapperapi.yml deleted file mode 100644 index c98cf7d..0000000 --- a/FP/scrapper/target/classes/scrapperapi.yml +++ /dev/null @@ -1,184 +0,0 @@ -openapi: 3.0.1 -info: - title: Scrapper API - version: 1.0.0 - contact: - name: Alexander Biryukov - url: https://github.com -paths: - /tg-chat/{id}: - post: - summary: Зарегистрировать чат - parameters: - - name: id - in: path - required: true - schema: - type: integer - format: int64 - responses: - '200': - description: Чат зарегистрирован - '400': - description: Некорректные параметры запроса - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorResponse' - delete: - summary: Удалить чат - parameters: - - name: id - in: path - required: true - schema: - type: integer - format: int64 - responses: - '200': - description: Чат успешно удалён - '400': - description: Некорректные параметры запроса - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorResponse' - '404': - description: Чат не существует - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorResponse' - /links: - get: - summary: Получить все отслеживаемые ссылки - parameters: - - name: Tg-Chat-Id - in: header - required: true - schema: - type: integer - format: int64 - responses: - '200': - description: Ссылки успешно получены - content: - application/json: - schema: - $ref: '#/components/schemas/ListLinksResponse' - '400': - description: Некорректные параметры запроса - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorResponse' - post: - summary: Добавить отслеживание ссылки - parameters: - - name: Tg-Chat-Id - in: header - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/AddLinkRequest' - required: true - responses: - '200': - description: Ссылка успешно добавлена - content: - application/json: - schema: - $ref: '#/components/schemas/LinkResponse' - '400': - description: Некорректные параметры запроса - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorResponse' - delete: - summary: Убрать отслеживание ссылки - parameters: - - name: Tg-Chat-Id - in: header - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/RemoveLinkRequest' - required: true - responses: - '200': - description: Ссылка успешно убрана - content: - application/json: - schema: - $ref: '#/components/schemas/LinkResponse' - '400': - description: Некорректные параметры запроса - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorResponse' - '404': - description: Ссылка не найдена - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorResponse' -components: - schemas: - LinkResponse: - type: object - properties: - id: - type: integer - format: int64 - url: - type: string - format: uri - ApiErrorResponse: - type: object - properties: - description: - type: string - code: - type: string - exceptionName: - type: string - exceptionMessage: - type: string - stacktrace: - type: array - items: - type: string - AddLinkRequest: - type: object - properties: - link: - type: string - format: uri - ListLinksResponse: - type: object - properties: - links: - type: array - items: - $ref: '#/components/schemas/LinkResponse' - size: - type: integer - format: int32 - RemoveLinkRequest: - type: object - properties: - link: - type: string - format: uri From d19eaa4bcaf8c088382eb65ae8dea3574f82fe03 Mon Sep 17 00:00:00 2001 From: Ray-Not <2sinsincuba@gmail.com> Date: Fri, 19 May 2023 18:45:33 +0500 Subject: [PATCH 8/9] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D1=81=D0=B2=D1=8F=D0=B7=D0=B8=20=D0=91?= =?UTF-8?q?=D0=94=20=D0=B8=20=D0=B1=D0=BE=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FP/bot/pom.xml | 16 +++++++ .../tinkoff/edu/java/bot/BotApplication.java | 8 +++- .../edu/java/bot/configuration/jdbcBean.java | 26 ++++++++++ .../records/ApplicationConfig.java | 3 ++ .../tinkoff/edu/java/bot/handler/BotMain.java | 19 ++++---- .../edu/java/bot/handler/MessageHandler.java | 21 +++++--- .../tinkoff/edu/java/bot/handler/Updater.java | 9 +++- .../edu/java/bot/handler/commands/List.java | 35 ++++++++++++-- .../edu/java/bot/handler/commands/Start.java | 16 +++++-- .../edu/java/bot/handler/commands/Track.java | 48 ++++++++++++++++--- .../java/bot/handler/commands/Untrack.java | 24 +++++++--- .../src/main/resources/application.properties | 5 +- FP/bot/src/test/java/BotTest.java | 24 ---------- FP/docker-compose.yml | 4 +- .../java/scrapper/ScrapperApplication.java | 14 +++--- .../java/scrapper/jdbc/JdbcLinkService.java | 16 +++++-- .../java/scrapper/jdbc/config/jdbcBean.java | 2 +- .../jdbc/operations/LinkOperations.java | 8 ++-- 18 files changed, 213 insertions(+), 85 deletions(-) create mode 100644 FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/jdbcBean.java delete mode 100644 FP/bot/src/test/java/BotTest.java diff --git a/FP/bot/pom.xml b/FP/bot/pom.xml index 3b3c9e6..96dea0d 100644 --- a/FP/bot/pom.xml +++ b/FP/bot/pom.xml @@ -90,5 +90,21 @@ spring-boot-starter-amqp 3.0.6 + + + org.springframework.boot + spring-boot-starter-jdbc + + + org.postgresql + postgresql + runtime + + + org.example + scrapper + 1.0 + compile + \ No newline at end of file diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java index 0bdeff0..92ae210 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/BotApplication.java @@ -1,11 +1,16 @@ package ru.tinkoff.edu.java.bot; import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.jdbc.core.JdbcTemplate; import ru.tinkoff.edu.java.bot.configuration.records.ApplicationConfig; import ru.tinkoff.edu.java.bot.handler.BotMain; +import javax.sql.DataSource; + @SpringBootApplication @EnableConfigurationProperties(ApplicationConfig.class) @@ -14,7 +19,8 @@ public class BotApplication public static void main(String[] args){ var ctx = SpringApplication.run(BotApplication.class, args); ApplicationConfig config = ctx.getBean(ApplicationConfig.class); - BotMain bot = new BotMain(config.bot().token()); + JdbcTemplate jdbcTemplate = (JdbcTemplate) ctx.getBean("jdbcTemplate"); + BotMain bot = new BotMain(config.bot().token(), jdbcTemplate); bot.start(); } } diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/jdbcBean.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/jdbcBean.java new file mode 100644 index 0000000..e768de5 --- /dev/null +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/jdbcBean.java @@ -0,0 +1,26 @@ +package ru.tinkoff.edu.java.bot.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.DriverManagerDataSource; + +import javax.sql.DataSource; + +@Configuration +public class jdbcBean { + @Bean + public DataSource dataSource() { + DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName("org.postgresql.Driver"); + dataSource.setUrl("jdbc:postgresql://localhost:5432/postgres"); + dataSource.setUsername("scrap_user"); + dataSource.setPassword("hard_password"); + + return dataSource; + } + @Bean + public JdbcTemplate jdbcTemplate () { + return new JdbcTemplate (dataSource()); + } +} diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/ApplicationConfig.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/ApplicationConfig.java index 5ee81b6..c23d07b 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/ApplicationConfig.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/configuration/records/ApplicationConfig.java @@ -1,12 +1,15 @@ package ru.tinkoff.edu.java.bot.configuration.records; import jakarta.validation.constraints.NotNull; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.validation.annotation.Validated; @Validated @EnableScheduling +@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) @ConfigurationProperties(prefix = "app", ignoreUnknownFields = false) public record ApplicationConfig( @NotNull String test, diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/BotMain.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/BotMain.java index 33e72c8..13d6b65 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/BotMain.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/BotMain.java @@ -2,35 +2,32 @@ import com.pengrad.telegrambot.TelegramBot; import com.pengrad.telegrambot.request.SendMessage; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.jdbc.core.JdbcTemplate; import ru.tinkoff.edu.java.bot.configuration.records.ApplicationConfig; +@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) @EnableConfigurationProperties(ApplicationConfig.class) public class BotMain { String token; static TelegramBot bot; + private JdbcTemplate jdbcTemplate; - public BotMain(String token) { + public BotMain(String token, JdbcTemplate jdbcTemplate) { this.token = token; + this.jdbcTemplate = jdbcTemplate; } public void start() { bot = new TelegramBot(token); - bot.setUpdatesListener(new Updater(bot)); + bot.setUpdatesListener(new Updater(bot, jdbcTemplate)); } public void end() { bot.removeGetUpdatesListener(); } - - public static void apiCommand(long tgChatId, String command) { - - MessageHandler handler = new MessageHandler(); - String[] parse = command.split(" "); - if(parse.length > 1) command = handler.call_command(parse[0], parse[1]); - else command = handler.call_command(parse[0]); - bot.execute(new SendMessage(tgChatId, command)); - } } diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/MessageHandler.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/MessageHandler.java index 56cfd57..87f2ab0 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/MessageHandler.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/MessageHandler.java @@ -1,29 +1,38 @@ package ru.tinkoff.edu.java.bot.handler; +import org.springframework.jdbc.core.JdbcTemplate; import ru.tinkoff.edu.java.bot.handler.commands.All; public class MessageHandler extends All { + private final JdbcTemplate jdbcTemplate; + private final long chatid; + + public MessageHandler(JdbcTemplate jdbcTemplate, long chatid) { + this.jdbcTemplate = jdbcTemplate; + this.chatid = chatid; + } + public boolean is_command(String message) { return message.startsWith("/"); } public String call_command(String command, String arg) { return switch (command) { - case "/start" -> start(); + case "/start" -> start(jdbcTemplate, chatid); case "/help" -> help(); - case "/track" -> track(arg); - case "/list" -> list(); - case "/untrack" -> untrack(arg); + case "/track" -> track(jdbcTemplate, arg, chatid); + case "/list" -> list(jdbcTemplate, chatid); + case "/untrack" -> untrack(jdbcTemplate, arg, chatid); default -> unknow(); }; } public String call_command(String command) { return switch (command) { - case "/start" -> start(); + case "/start" -> start(jdbcTemplate, chatid); case "/help" -> help(); - case "/list" -> list(); + case "/list" -> list(jdbcTemplate, chatid); default -> unknow(); }; } diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/Updater.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/Updater.java index 746ad5e..7965170 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/Updater.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/Updater.java @@ -5,22 +5,27 @@ import com.pengrad.telegrambot.model.Update; import com.pengrad.telegrambot.model.request.*; import com.pengrad.telegrambot.request.SendMessage; +import org.springframework.jdbc.core.JdbcTemplate; import java.util.List; public class Updater implements UpdatesListener { - MessageHandler handler = new MessageHandler(); + MessageHandler handler; String command; TelegramBot bot; + private JdbcTemplate jdbcTemplate; + private long chatid; - public Updater(TelegramBot bot) { + public Updater(TelegramBot bot, JdbcTemplate jdbcTemplate) { this.bot = bot; + this.jdbcTemplate = jdbcTemplate; } @Override public int process(List updates) { Update update = updates.get(0); + handler = new MessageHandler(jdbcTemplate, update.message().chat().id()); if(handler.is_command(update.message().text())) { String[] parse = update.message().text().split(" "); if(parse.length > 1) command = handler.call_command(parse[0], parse[1]); diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/List.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/List.java index fdadd4f..280f80a 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/List.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/List.java @@ -1,10 +1,37 @@ package ru.tinkoff.edu.java.bot.handler.commands; +import com.google.gson.JsonObject; +import okhttp3.Interceptor; +import org.springframework.jdbc.BadSqlGrammarException; +import org.springframework.jdbc.core.JdbcTemplate; import ru.tinkoff.edu.java.bot.handler.DB; +import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.UnauthorizationException; +import ru.tinkoff.edu.java.scrapper.jdbc.operations.ChatOperations; +import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkChatOperations; +import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkOperations; -public interface List { - default String list() { - if(DB.listIsEmpty()) return "list пустой"; - return "Отслеживаемые ссылки: " + DB.getListParse() + ""; +import java.util.ArrayList; + +public interface List extends LinkOperations, ChatOperations, LinkChatOperations { + + default String list(JdbcTemplate jdbc, long chat) { + int i; + String links = ""; + int chat_id = i_findChat(jdbc, chat); + if (chat_id == 0) { + return "Перед использованием нужно зарегистрироваться"; + } + ArrayList link_list = new ArrayList<>(); + try { + for (i = 0; i < i_get_all_links_for_chat(jdbc, chat_id).size(); i++) { + link_list.add(i_get_all_links_for_chat(jdbc, chat_id).get(i).linkid()); + } + for (i = 0; i < i_findAllLink(jdbc, link_list).size(); i++) { + links += i_findAllLink(jdbc, link_list).get(i).url() + "\n"; + } + return links; + } catch (BadSqlGrammarException e) { + return "У вас нет ссылок"; + } } } diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Start.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Start.java index 5c4b5d7..d2d5459 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Start.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Start.java @@ -1,9 +1,19 @@ package ru.tinkoff.edu.java.bot.handler.commands; -public interface Start { +import org.springframework.jdbc.core.JdbcTemplate; +import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.EntryExsistException; +import ru.tinkoff.edu.java.scrapper.jdbc.operations.ChatOperations; + +public interface Start extends ChatOperations { - default String start() { - return "Бот начал работу"; + default String start(JdbcTemplate jdbc, long chat) { + int chat_id = i_findChat(jdbc, chat); + if (chat_id != 0) { + return "Вы уже зарегистрированы"; + } else { + i_addChat(jdbc, chat); + return "Регистрация успешна, ваш tg_id = " + chat; + } } } diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Track.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Track.java index fcd1042..9080b48 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Track.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Track.java @@ -1,13 +1,47 @@ package ru.tinkoff.edu.java.bot.handler.commands; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.web.reactive.function.client.WebClientResponseException; import ru.tinkoff.edu.java.bot.handler.DB; +import ru.tinkoff.edu.java.linkparser.LinkParser; +import ru.tinkoff.edu.java.scrapper.client.ClientConfiguration; +import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.EntryExsistException; +import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.EntryNotExsistException; +import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.NullLinkException; +import ru.tinkoff.edu.java.scrapper.exceptions.customExceptions.UnauthorizationException; +import ru.tinkoff.edu.java.scrapper.jdbc.operations.ChatOperations; +import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkChatOperations; +import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkOperations; +import ru.tinkoff.edu.java.scrapper.model.RemoveLinkRequest; -public interface Track { - default String track(String link) { - link = link.trim(); - if(link.equals("")) return "ведите ссылку"; - if(DB.linkContain(link)) return "Ссылка уже есть"; - DB.addLink(link); - return "ссылка " + link + " добавлена"; +public interface Track extends LinkOperations, LinkChatOperations, ChatOperations { + default String track(JdbcTemplate jdbc, String link, long chat) { + ClientConfiguration client = new ClientConfiguration(); + LinkParser parser = new LinkParser(); + if (parser.getLink(link) == null) { + return "Ссылка невалидна"; + } + try { + client.gitHubClient(parser.getLink(link)); + } catch (WebClientResponseException e) { + try { + client.stackOverflowClient(parser.getLink(link)); + } catch (WebClientResponseException ex) { + return "Ссылка не поддерживается, доступны: Git, StackOverFlow"; + } + } + int link_id = i_findLink(jdbc, link); + int chat_id = i_findChat(jdbc, chat); + if (chat_id == 0) { + return "Перед использованием нужно зарегистрироваться"; + } + if (link_id == 0) { + i_addLink(jdbc, link); + link_id = i_findLink(jdbc, link); + } + if (i_findLinkChat(jdbc, link_id, chat_id)) { + addLinkChat(jdbc, link_id, chat_id); + return "Ссылка успешно добавлена!"; + }else return"Ссылка уже добавлена!"; } } diff --git a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Untrack.java b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Untrack.java index a196195..6615feb 100644 --- a/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Untrack.java +++ b/FP/bot/src/main/java/ru/tinkoff/edu/java/bot/handler/commands/Untrack.java @@ -1,14 +1,24 @@ package ru.tinkoff.edu.java.bot.handler.commands; +import org.springframework.jdbc.core.JdbcTemplate; import ru.tinkoff.edu.java.bot.handler.DB; +import ru.tinkoff.edu.java.scrapper.jdbc.operations.ChatOperations; +import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkChatOperations; +import ru.tinkoff.edu.java.scrapper.jdbc.operations.LinkOperations; -public interface Untrack { - default String untrack(String link) { - if(link.equals("")) return "ведите ссылку"; - if(DB.linkContain(link)) { - DB.rmLink(link); - return "ссылка " + link + " удалена"; +public interface Untrack extends LinkOperations, LinkChatOperations, ChatOperations { + default String untrack(JdbcTemplate jdbc, String link, long chat) { + int link_id = i_findLink(jdbc, link); + int chat_id = i_findChat(jdbc, chat); + if (chat_id == 0) { + return "Перед использованием нужно зарегистрироваться"; } - return "ссылки " + link + " нет в пуле"; + if (link_id != 0) { + i_removeLink(jdbc, link); + if (!i_findLinkChat(jdbc, link_id, chat_id)) { + i_removeLinkChat(jdbc, link_id, chat_id); + } + return "Ссылка удалена"; + } else return "Ссылки не существует"; } } diff --git a/FP/bot/src/main/resources/application.properties b/FP/bot/src/main/resources/application.properties index 95d9a47..6600aaa 100644 --- a/FP/bot/src/main/resources/application.properties +++ b/FP/bot/src/main/resources/application.properties @@ -3,4 +3,7 @@ springdoc.swagger-ui.path=/swagger-ui app.scheduler.interval=50000 app.bot.token=5805337447:AAGnmh2isW2115L7tJWFojbpmSjNrarTvxQ app.bot.name=@SFRETbot -server.port=8081 \ No newline at end of file +server.port=8081 +app.exchange=my-direct-exchange +app.queue=my-queue +app.routingKey=my-routing-key \ No newline at end of file diff --git a/FP/bot/src/test/java/BotTest.java b/FP/bot/src/test/java/BotTest.java deleted file mode 100644 index 4e14a70..0000000 --- a/FP/bot/src/test/java/BotTest.java +++ /dev/null @@ -1,24 +0,0 @@ -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import ru.tinkoff.edu.java.bot.handler.DB; -import ru.tinkoff.edu.java.bot.handler.MessageHandler; - - -public class BotTest { - - String except_empty_list = "list пустой"; - String except_unknow_command = "Неизвестная команда"; - MessageHandler handler = new MessageHandler(); - - @Test - public void listTest() { - Assertions.assertEquals(handler.call_command("/list"), except_empty_list); - DB.addLink("link"); - Assertions.assertNotEquals(handler.call_command("/list"), except_empty_list); - } - - @Test - public void unknowCommandAndFormatTest() { - Assertions.assertEquals(handler.call_command("/uno"), except_unknow_command); - } -} diff --git a/FP/docker-compose.yml b/FP/docker-compose.yml index 1d76d36..4195e6e 100644 --- a/FP/docker-compose.yml +++ b/FP/docker-compose.yml @@ -5,7 +5,7 @@ services: container_name: postgres image: postgres:15.2 environment: - POSTGRES_DB: scrapper + POSTGRES_DB: postgres POSTGRES_USER: scrap_user POSTGRES_PASSWORD: hard_password volumes: @@ -27,7 +27,7 @@ services: - --hub-mode=off - --changelog-file=master.xml - --driver=org.postgresql.Driver - - --url=jdbc:postgresql://postgres:5432/scrapper + - --url=jdbc:postgresql://postgres:5432/postgres - --username=scrap_user - --password=hard_password - --logLevel=debug diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java index c2e1b98..0539e02 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java @@ -1,7 +1,6 @@ package ru.tinkoff.edu.java.scrapper; import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -19,11 +18,12 @@ public class ScrapperApplication { public static void main(String[] args) { var ctx = SpringApplication.run(ScrapperApplication.class, args); ApplicationConfig config = ctx.getBean(ApplicationConfig.class); - System.out.println("----------------------------------------------------------------" + config); - SendNoticeServiceQueue notificationService = new SendNoticeServiceQueue(new ScrapperQueueProducer( - new RabbitTemplate(), - config - )); - notificationService.sendNotice("Вот-вот"); + System.out.println("----------------------------------------------------------------"); +// SendNoticeServiceQueue notificationService = new SendNoticeServiceQueue(new ScrapperQueueProducer( +// new RabbitTemplate(), +// config +// )); +// notificationService.sendNotice("Вот-вот"); +// Cannot invoke "org.springframework.amqp.rabbit.connection.ConnectionFactory.createConnection()" because "connectionFactory" is null } } diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java index 380ca48..2d62856 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/JdbcLinkService.java @@ -1,5 +1,6 @@ package ru.tinkoff.edu.java.scrapper.jdbc; +import org.springframework.jdbc.BadSqlGrammarException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.web.reactive.function.client.WebClientResponseException; import ru.tinkoff.edu.java.linkparser.LinkParser; @@ -37,7 +38,7 @@ public void addLink(JdbcTemplate jdbc, AddLinkRequest link, Long chat) { throw new UnauthorizationException("Перед использованием нужно зарегистрироваться"); } if (link_id == 0) { - i_addLink(jdbc, link); + i_addLink(jdbc, link.link()); link_id = i_findLink(jdbc, link.link()); } if (i_findLinkChat(jdbc, link_id, chat_id)) { @@ -52,7 +53,7 @@ public void removeLink(JdbcTemplate jdbc, RemoveLinkRequest link, long chat) { throw new UnauthorizationException("Перед использованием нужно зарегистрироваться"); } if (link_id != 0) { - i_removeLink(jdbc, link); + i_removeLink(jdbc, link.link()); } else throw new EntryNotExsistException("Ссылки не существует"); if (!i_findLinkChat(jdbc, link_id, chat_id)) { i_removeLinkChat(jdbc, link_id, chat_id); @@ -66,10 +67,15 @@ public List getLinks(JdbcTemplate jdbc, long chat) { throw new UnauthorizationException("Перед использованием нужно зарегистрироваться"); } ArrayList link_list = new ArrayList<>(); - for (i = 0; i < i_get_all_links_for_chat(jdbc, chat_id).size(); i++){ - link_list.add(i_get_all_links_for_chat(jdbc, chat_id).get(i).linkid()); + try { + for (i = 0; i < i_get_all_links_for_chat(jdbc, chat_id).size(); i++) { + link_list.add(i_get_all_links_for_chat(jdbc, chat_id).get(i).linkid()); + } + return i_findAllLink(jdbc, link_list); + } catch (BadSqlGrammarException e) { + throw new EntryNotExsistException("У вас нет ссылок"); } - return i_findAllLink(jdbc, link_list); + } } diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/config/jdbcBean.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/config/jdbcBean.java index 8db6ed9..74a1fbe 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/config/jdbcBean.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/config/jdbcBean.java @@ -12,7 +12,7 @@ public class jdbcBean { public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("org.postgresql.Driver"); - dataSource.setUrl("jdbc:postgresql://localhost:5432/scrapper"); + dataSource.setUrl("jdbc:postgresql://localhost:5432/postgres"); dataSource.setUsername("scrap_user"); dataSource.setPassword("hard_password"); diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java index 7907633..dfdbe71 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/jdbc/operations/LinkOperations.java @@ -13,7 +13,7 @@ public interface LinkOperations { default void i_addLink( JdbcTemplate jdbcTemplate, - AddLinkRequest addLinkRequest + String link ) { int link_id; @@ -26,15 +26,15 @@ default void i_addLink( link_id = 1; } - jdbcTemplate.update("INSERT INTO links VALUES(?, ?)", link_id, addLinkRequest.link()); + jdbcTemplate.update("INSERT INTO links VALUES(?, ?)", link_id, link); } default void i_removeLink( JdbcTemplate jdbcTemplate, - RemoveLinkRequest removeLinkRequest + String link ){ String query = "DELETE FROM links where link IN ('%s')"; - query = query.formatted(removeLinkRequest.link()); + query = query.formatted(link); jdbcTemplate.update(query); } From b5dde2a410fa96a50411406d9e2be7112e00c44f Mon Sep 17 00:00:00 2001 From: Ray-Not <2sinsincuba@gmail.com> Date: Fri, 19 May 2023 18:59:25 +0500 Subject: [PATCH 9/9] =?UTF-8?q?=D0=B0=D0=BD=D0=BD=D0=BE=D1=82=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=BD=D0=B5=20=D0=BF=D0=BE=D0=BC=D0=BE=D0=B3?= =?UTF-8?q?=D0=BB=D0=B0=20PS=20Rabbit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java | 3 +-- .../edu/java/scrapper/configuration/ApplicationConfig.java | 2 ++ .../edu/java/scrapper/configuration/RabbitMQConfiguration.java | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java index 0539e02..1ef6a07 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/ScrapperApplication.java @@ -24,6 +24,5 @@ public static void main(String[] args) { // config // )); // notificationService.sendNotice("Вот-вот"); -// Cannot invoke "org.springframework.amqp.rabbit.connection.ConnectionFactory.createConnection()" because "connectionFactory" is null - } + } } diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java index 52af096..2651ea3 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/ApplicationConfig.java @@ -6,6 +6,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Import; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.validation.annotation.Validated; import ru.tinkoff.edu.java.scrapper.rabbitmq.ScrapperQueueProducer; @@ -17,6 +18,7 @@ @Validated @ConfigurationProperties(prefix = "app", ignoreUnknownFields = false) @EnableScheduling +@Import(RabbitMQConfiguration.class) public record ApplicationConfig( @NotNull String test, @NotNull Scheduler scheduler, diff --git a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java index 8682387..fc60661 100644 --- a/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java +++ b/FP/scrapper/src/main/java/ru/tinkoff/edu/java/scrapper/configuration/RabbitMQConfiguration.java @@ -61,7 +61,7 @@ public MessageConverter jsonMessageConverter(ClassMapper classMapper){ @Bean public ConnectionFactory connectionFactory() { - CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost", 5672); + CachingConnectionFactory connectionFactory = new CachingConnectionFactory("rabbitmq", 5672); connectionFactory.setUsername("guest"); connectionFactory.setPassword("guest"); // Другие настройки, если необходимо