From 0cb4e0f50eb48af40463b3a19e8abcbb372d7edd Mon Sep 17 00:00:00 2001 From: Igor Korolevich Date: Mon, 15 Jan 2024 13:23:16 +0200 Subject: [PATCH 01/13] added liquibase script for adding chatId collumn --- .../application/bookingservice/model/Customer.java | 3 ++- .../changes/11-add-column-customer-table.yaml | 11 +++++++++++ .../resources/db/changelog/db.changelog-master.yaml | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/db/changelog/changes/11-add-column-customer-table.yaml diff --git a/src/main/java/com/application/bookingservice/model/Customer.java b/src/main/java/com/application/bookingservice/model/Customer.java index 5cc13f8..23852b4 100644 --- a/src/main/java/com/application/bookingservice/model/Customer.java +++ b/src/main/java/com/application/bookingservice/model/Customer.java @@ -47,9 +47,10 @@ public class Customer implements UserDetails { inverseJoinColumns = @JoinColumn(name = "role_id") ) private Set roles = new HashSet<>(); + @Column(name = "chat_id") + private Long chatId; @Column(name = "is_deleted", nullable = false) private Boolean isDeleted = false; - @Override public Collection getAuthorities() { return roles; diff --git a/src/main/resources/db/changelog/changes/11-add-column-customer-table.yaml b/src/main/resources/db/changelog/changes/11-add-column-customer-table.yaml new file mode 100644 index 0000000..f34a9ef --- /dev/null +++ b/src/main/resources/db/changelog/changes/11-add-column-customer-table.yaml @@ -0,0 +1,11 @@ +databaseChangeLog: + - changeSet: + id: add-column-customer-table + author: BINOV_team + changes: + - addColumn: + tableName: customers + columns: + - column: + name: chat_id + type: bigint diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 1e82b96..1a56bb9 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -19,3 +19,5 @@ databaseChangeLog: file: db/changelog/changes/09-insert-customers.yaml - include: file: db/changelog/changes/10-insert-demo-customers-roles.yaml + - include: + file: db/changelog/changes/11-add-column-customer-table.yaml From 1717c16b1d16c055275c5c0abc32c34b823b24b7 Mon Sep 17 00:00:00 2001 From: Igor Korolevich Date: Mon, 15 Jan 2024 13:23:29 +0200 Subject: [PATCH 02/13] added some methods --- .../repository/customer/CustomerRepository.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/application/bookingservice/repository/customer/CustomerRepository.java b/src/main/java/com/application/bookingservice/repository/customer/CustomerRepository.java index 912bd46..3fb5eb4 100644 --- a/src/main/java/com/application/bookingservice/repository/customer/CustomerRepository.java +++ b/src/main/java/com/application/bookingservice/repository/customer/CustomerRepository.java @@ -1,6 +1,8 @@ package com.application.bookingservice.repository.customer; import com.application.bookingservice.model.Customer; + +import java.util.List; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @@ -10,4 +12,8 @@ public interface CustomerRepository extends JpaRepository { @Query("SELECT c FROM Customer c JOIN FETCH c.roles r WHERE c.email = :email") Optional findByEmail(String email); + + Optional findByChatId(Long chatId); + + List findAllByChatIdNotNull(); } From cd47f16eecd2d272e035356e52be2330012f880d Mon Sep 17 00:00:00 2001 From: Igor Korolevich Date: Mon, 15 Jan 2024 13:23:57 +0200 Subject: [PATCH 03/13] added send text to all and auth with stop command --- .../bookingservice/bot/NotificationBot.java | 108 ++++++++++++++++-- 1 file changed, 100 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/application/bookingservice/bot/NotificationBot.java b/src/main/java/com/application/bookingservice/bot/NotificationBot.java index f2a559f..8f903b4 100644 --- a/src/main/java/com/application/bookingservice/bot/NotificationBot.java +++ b/src/main/java/com/application/bookingservice/bot/NotificationBot.java @@ -1,28 +1,54 @@ package com.application.bookingservice.bot; +import com.application.bookingservice.dto.customer.CustomerLoginRequestDto; import com.application.bookingservice.exception.TelegramMessageException; +import com.application.bookingservice.model.Customer; +import com.application.bookingservice.repository.customer.CustomerRepository; +import jakarta.persistence.EntityNotFoundException; import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.stereotype.Component; import org.telegram.telegrambots.bots.TelegramLongPollingBot; import org.telegram.telegrambots.meta.api.methods.send.SendMessage; import org.telegram.telegrambots.meta.api.objects.Update; import org.telegram.telegrambots.meta.exceptions.TelegramApiException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; @Component public class NotificationBot extends TelegramLongPollingBot { private static final Long CHAT_ID = -1002107651145L; private static final String START_COMMAND = "/start"; - private static final String CANT_HANDLE_START_MESSAGE = "Can't handle start command"; + private static final String AUTH_COMMAND = "/auth"; + private static final String CANCEL_COMMAND = "/cancel"; private static final String CANT_LOG_MESSAGE = "Can't send logs to chat text: %s"; private static final String CANT_SEND_MESSAGE = "Can't send message to user chatId: %d"; - private static final String START_MESSAGE = "Hello, I am a bot for logging in BINOV booking"; + private static final String START_MESSAGE = "Hello, I am a bot for logging in BINOV booking \n " + + "please use /auth to start recive messages"; private final String botName; + private final CustomerRepository customerRepository; + private CustomerLoginRequestDto requestDto; + private final AuthenticationManager authenticationManager; + private Map authStates = new HashMap<>(); + private Map loginData = new HashMap<>(); + + private enum AuthState { + STARTED, + LOGIN, + PASSWORD + } public NotificationBot( @Value("${bot.token}") String token, - @Value("${bot.name}") String botName + @Value("${bot.name}") String botName, + CustomerRepository customerRepository, + AuthenticationManager authenticationManager ) { super(token); + this.customerRepository = customerRepository; + this.authenticationManager = authenticationManager; this.botName = botName; } @@ -33,12 +59,78 @@ public String getBotUsername() { @Override public void onUpdateReceived(Update update) { - try { - if (update.getMessage().getText().equals(START_COMMAND)) { - handleStartCommand(update); + sendTextMessageToAll(update.getMessage().getText()); + Long chatId = update.getMessage().getChatId(); + AuthState currentState = authStates.getOrDefault(chatId, AuthState.STARTED); + String recivedText = update.getMessage().getText(); + if (recivedText.equals(START_COMMAND)) { + handleStartCommand(update); + } else if (authStates.containsKey(chatId)) { + switch (currentState) { + case STARTED: + sendTextMessage(chatId, "Please enter your login:"); + authStates.put(chatId, AuthState.LOGIN); + break; + case LOGIN: + requestDto = loginData.getOrDefault(chatId, new CustomerLoginRequestDto()); + requestDto.setEmail(recivedText); + sendTextMessage(chatId, "Password:"); + loginData.put(chatId, requestDto); + authStates.put(chatId, AuthState.PASSWORD); + break; + case PASSWORD: + requestDto = loginData.getOrDefault(chatId, new CustomerLoginRequestDto()); + requestDto.setPassword(recivedText); + try { + authenticationManager.authenticate(new UsernamePasswordAuthenticationToken( + requestDto.getEmail(), requestDto.getPassword() + )); + Customer customer = customerRepository.findByEmail(requestDto.getEmail()).orElseThrow( + () -> new EntityNotFoundException("Can't find customer") + ); + customer.setChatId(chatId); + customerRepository.save(customer); + sendTextMessage(chatId, "Successful, now you will receive " + + "notifications from BINOV_booking"); + } catch (Exception e) { + sendTextMessage(chatId, "Wrong password or login please try again"); + } finally { + authStates.remove(chatId); + requestDto.setPassword(""); + } + break; } - } catch (Exception e) { - throw new TelegramMessageException(CANT_HANDLE_START_MESSAGE, e); + } else if (recivedText.equals(AUTH_COMMAND)) { + sendTextMessage(chatId, "Please enter your login:"); + authStates.put(chatId, AuthState.LOGIN); + } else if (recivedText.equals(CANCEL_COMMAND)) { + Customer customer = customerRepository.findByChatId(chatId).orElseThrow( + () -> new EntityNotFoundException("can't find customer by chat id") + ); + customer.setChatId(null); + customerRepository.save(customer); + sendTextMessage(chatId, "notification canceled successful"); + } else { + sendTextMessage(chatId, "hello im BINOV_booking_bot use /auth command if you haven't done it yet to receive notification or /cancel to stop receive messages"); + } + } + + private void sendTextMessageToAll(String text) { + List allByChatIdNotNull = customerRepository.findAllByChatIdNotNull(); + for (int i = 0; i < allByChatIdNotNull.size(); i++) { + sendTextMessage(allByChatIdNotNull.get(i).getChatId(), text); + } + } + + private void sendTextMessage(long chatId, String text) { + SendMessage message = new SendMessage(); + message.setChatId(chatId); + message.setText(text); + + try { + execute(message); + } catch (TelegramApiException e) { + throw new RuntimeException(); } } From 1187fee0951314905a12326cf6093befc7ede9bf Mon Sep 17 00:00:00 2001 From: Igor Korolevich Date: Tue, 16 Jan 2024 10:13:11 +0200 Subject: [PATCH 04/13] updated some method in NotificationBot --- .../bookingservice/bot/NotificationBot.java | 97 +++++++++++-------- 1 file changed, 58 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/application/bookingservice/bot/NotificationBot.java b/src/main/java/com/application/bookingservice/bot/NotificationBot.java index 8f903b4..b03f4a9 100644 --- a/src/main/java/com/application/bookingservice/bot/NotificationBot.java +++ b/src/main/java/com/application/bookingservice/bot/NotificationBot.java @@ -11,6 +11,7 @@ import org.springframework.stereotype.Component; import org.telegram.telegrambots.bots.TelegramLongPollingBot; import org.telegram.telegrambots.meta.api.methods.send.SendMessage; +import org.telegram.telegrambots.meta.api.methods.updatingmessages.DeleteMessage; import org.telegram.telegrambots.meta.api.objects.Update; import org.telegram.telegrambots.meta.exceptions.TelegramApiException; import java.util.HashMap; @@ -25,8 +26,8 @@ public class NotificationBot extends TelegramLongPollingBot { private static final String CANCEL_COMMAND = "/cancel"; private static final String CANT_LOG_MESSAGE = "Can't send logs to chat text: %s"; private static final String CANT_SEND_MESSAGE = "Can't send message to user chatId: %d"; - private static final String START_MESSAGE = "Hello, I am a bot for logging in BINOV booking \n " - + "please use /auth to start recive messages"; + private static final String START_MESSAGE = "hello im BINOV_booking_bot use /auth command " + + "if you haven't done it yet to receive notification or /cancel to stop receive messages"; private final String botName; private final CustomerRepository customerRepository; private CustomerLoginRequestDto requestDto; @@ -66,40 +67,7 @@ public void onUpdateReceived(Update update) { if (recivedText.equals(START_COMMAND)) { handleStartCommand(update); } else if (authStates.containsKey(chatId)) { - switch (currentState) { - case STARTED: - sendTextMessage(chatId, "Please enter your login:"); - authStates.put(chatId, AuthState.LOGIN); - break; - case LOGIN: - requestDto = loginData.getOrDefault(chatId, new CustomerLoginRequestDto()); - requestDto.setEmail(recivedText); - sendTextMessage(chatId, "Password:"); - loginData.put(chatId, requestDto); - authStates.put(chatId, AuthState.PASSWORD); - break; - case PASSWORD: - requestDto = loginData.getOrDefault(chatId, new CustomerLoginRequestDto()); - requestDto.setPassword(recivedText); - try { - authenticationManager.authenticate(new UsernamePasswordAuthenticationToken( - requestDto.getEmail(), requestDto.getPassword() - )); - Customer customer = customerRepository.findByEmail(requestDto.getEmail()).orElseThrow( - () -> new EntityNotFoundException("Can't find customer") - ); - customer.setChatId(chatId); - customerRepository.save(customer); - sendTextMessage(chatId, "Successful, now you will receive " - + "notifications from BINOV_booking"); - } catch (Exception e) { - sendTextMessage(chatId, "Wrong password or login please try again"); - } finally { - authStates.remove(chatId); - requestDto.setPassword(""); - } - break; - } + authProcess(currentState, chatId, update); } else if (recivedText.equals(AUTH_COMMAND)) { sendTextMessage(chatId, "Please enter your login:"); authStates.put(chatId, AuthState.LOGIN); @@ -111,18 +79,57 @@ public void onUpdateReceived(Update update) { customerRepository.save(customer); sendTextMessage(chatId, "notification canceled successful"); } else { - sendTextMessage(chatId, "hello im BINOV_booking_bot use /auth command if you haven't done it yet to receive notification or /cancel to stop receive messages"); + sendTextMessage(chatId, START_MESSAGE); } } - private void sendTextMessageToAll(String text) { + private void authProcess(AuthState currentState, Long chatId, Update update) { + String text = update.getMessage().getText(); + switch (currentState) { + case STARTED: + sendTextMessage(chatId, "Please enter your login:"); + authStates.put(chatId, AuthState.LOGIN); + break; + case LOGIN: + requestDto = loginData.getOrDefault(chatId, new CustomerLoginRequestDto()); + requestDto.setEmail(text); + sendTextMessage(chatId, "Password:"); + loginData.put(chatId, requestDto); + authStates.put(chatId, AuthState.PASSWORD); + break; + case PASSWORD: + requestDto = loginData.getOrDefault(chatId, new CustomerLoginRequestDto()); + requestDto.setPassword(text); + deletePreviousMessage(chatId, update); + try { + authenticationManager.authenticate(new UsernamePasswordAuthenticationToken( + requestDto.getEmail(), requestDto.getPassword() + )); + Customer customer = customerRepository.findByEmail(requestDto.getEmail()).orElseThrow( + () -> new EntityNotFoundException("Can't find customer") + ); + customer.setChatId(chatId); + customerRepository.save(customer); + sendTextMessage(chatId, "Successful, now you will receive " + + "notifications from BINOV_booking"); + } catch (Exception e) { + sendTextMessage(chatId, "Wrong password or login please try again"); + } finally { + authStates.remove(chatId); + requestDto.setPassword(""); + } + break; + } + } + + public void sendTextMessageToAll(String text) { List allByChatIdNotNull = customerRepository.findAllByChatIdNotNull(); for (int i = 0; i < allByChatIdNotNull.size(); i++) { sendTextMessage(allByChatIdNotNull.get(i).getChatId(), text); } } - private void sendTextMessage(long chatId, String text) { + public void sendTextMessage(long chatId, String text) { SendMessage message = new SendMessage(); message.setChatId(chatId); message.setText(text); @@ -157,4 +164,16 @@ private void handleStartCommand(Update update) { } } + private void deletePreviousMessage(Long chatId, Update update) { + int messageId = update.getMessage().getMessageId(); + DeleteMessage deleteMessage = new DeleteMessage(); + deleteMessage.setChatId(chatId); + deleteMessage.setMessageId(messageId); + try { + execute(deleteMessage); + } catch (TelegramApiException e) { + e.printStackTrace(); + } + } + } From 17b9103bab2d83905514e53bf203cf3ed9cef1e7 Mon Sep 17 00:00:00 2001 From: Igor Korolevich Date: Tue, 16 Jan 2024 10:50:02 +0200 Subject: [PATCH 05/13] added TelegramMessageException --- .../com/application/bookingservice/bot/NotificationBot.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/application/bookingservice/bot/NotificationBot.java b/src/main/java/com/application/bookingservice/bot/NotificationBot.java index b03f4a9..35297df 100644 --- a/src/main/java/com/application/bookingservice/bot/NotificationBot.java +++ b/src/main/java/com/application/bookingservice/bot/NotificationBot.java @@ -172,7 +172,7 @@ private void deletePreviousMessage(Long chatId, Update update) { try { execute(deleteMessage); } catch (TelegramApiException e) { - e.printStackTrace(); + throw new TelegramMessageException("Can't delete user message", e); } } From c66cf0f1a9c174b286577bc5f4bd0416cca7e091 Mon Sep 17 00:00:00 2001 From: Igor Korolevich Date: Tue, 16 Jan 2024 10:51:38 +0200 Subject: [PATCH 06/13] added methods to send notifications to users --- .../service/bot/NotificationService.java | 8 ++++ .../bot/TelegramNotificationService.java | 43 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/main/java/com/application/bookingservice/service/bot/NotificationService.java b/src/main/java/com/application/bookingservice/service/bot/NotificationService.java index 2bcfd99..853bc78 100644 --- a/src/main/java/com/application/bookingservice/service/bot/NotificationService.java +++ b/src/main/java/com/application/bookingservice/service/bot/NotificationService.java @@ -20,4 +20,12 @@ public interface NotificationService { Boolean paymentMessage(Payment payment); Boolean bookingExpiredMessage(String text); + + Boolean sendToUserBookingSuccessful(Long chatId, BookingResponseDto responseDto); + + Boolean sendToUserPayment(Long chatId, Payment payment); + + Boolean sendToUserNewAccommodation(Long chatId, AccommodationResponseDto responseDto); + + Boolean sendToAllUsers(String text); } diff --git a/src/main/java/com/application/bookingservice/service/bot/TelegramNotificationService.java b/src/main/java/com/application/bookingservice/service/bot/TelegramNotificationService.java index db8000d..10ef013 100644 --- a/src/main/java/com/application/bookingservice/service/bot/TelegramNotificationService.java +++ b/src/main/java/com/application/bookingservice/service/bot/TelegramNotificationService.java @@ -153,4 +153,47 @@ public Boolean bookingExpiredMessage(String text) { return true; } + @Override + public Boolean sendToUserBookingSuccessful(Long chatId, BookingResponseDto responseDto) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(" Dear user your booking was successful \n you check in data: ") + .append(responseDto.getCheckIn()) + .append(" \nyour check out date :") + .append(responseDto.getCheckOut()) + .append("\n Thanks for picking BINOVO_booking!"); + notificationBot.sendTextMessage(chatId, stringBuilder.toString()); + return true; + } + + @Override + public Boolean sendToUserPayment(Long chatId, Payment payment) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(" Dear user your payment was ") + .append(payment.getStatus()) + .append("\n total :") + .append(payment.getTotal()) + .append("\n Thanks for picking BINOVO_booking!"); + notificationBot.sendTextMessage(chatId, stringBuilder.toString()); + return true; + } + + @Override + public Boolean sendToUserNewAccommodation(Long chatId, AccommodationResponseDto responseDto) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(" Dear user we added new accommodation \n address: ") + .append(responseDto.getAddress()) + .append("\n type: ") + .append(responseDto.getType()) + .append("\n best price :") + .append(responseDto.getPrice()); + notificationBot.sendTextMessage(chatId, stringBuilder.toString()); + return true; + } + + @Override + public Boolean sendToAllUsers(String text) { + notificationBot.sendTextMessageToAll(text); + return true; + } + } From 1b43e1f855028451a42570c52d0535cbf5d9d1d3 Mon Sep 17 00:00:00 2001 From: Igor Korolevich Date: Tue, 16 Jan 2024 14:44:04 +0200 Subject: [PATCH 07/13] added sendMessageToUser --- .../service/accommodation/AccommodationServiceImpl.java | 1 + .../bookingservice/service/booking/BookingServiceImpl.java | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/main/java/com/application/bookingservice/service/accommodation/AccommodationServiceImpl.java b/src/main/java/com/application/bookingservice/service/accommodation/AccommodationServiceImpl.java index 10551c9..4ea6fe1 100644 --- a/src/main/java/com/application/bookingservice/service/accommodation/AccommodationServiceImpl.java +++ b/src/main/java/com/application/bookingservice/service/accommodation/AccommodationServiceImpl.java @@ -41,6 +41,7 @@ public AccommodationResponseDto save(AccommodationRequestDto accommodationReques .setAvailableUnits(accommodationRequestDto.getAvailableUnits()); AccommodationResponseDto savedAccommodationdto = accommodationMapper .toDto(accommodationRepository.save(accommodation)); + notificationService.sendToUserNewAccommodation(savedAccommodationdto); notificationService.accommodationCreatedMessage(savedAccommodationdto); return savedAccommodationdto; } diff --git a/src/main/java/com/application/bookingservice/service/booking/BookingServiceImpl.java b/src/main/java/com/application/bookingservice/service/booking/BookingServiceImpl.java index 1cc3f3e..090fffa 100644 --- a/src/main/java/com/application/bookingservice/service/booking/BookingServiceImpl.java +++ b/src/main/java/com/application/bookingservice/service/booking/BookingServiceImpl.java @@ -12,6 +12,7 @@ import com.application.bookingservice.exception.UnauthorizedActionException; import com.application.bookingservice.mapper.BookingMapper; import com.application.bookingservice.model.Booking; +import com.application.bookingservice.model.Customer; import com.application.bookingservice.repository.booking.BookingRepository; import com.application.bookingservice.repository.booking.spec.BookingSpecificationBuilder; import com.application.bookingservice.repository.customer.CustomerRepository; @@ -81,6 +82,12 @@ public BookingResponseDto save(Long customerId, BookingRequestDto requestBooking )); BookingResponseDto savedBookingDto = bookingMapper .toDto(bookingRepository.save(bookingToSave)); + Customer customer = customerRepository.findById(customerId).orElseThrow( + () -> new EntityNotFoundException(CUSTOMER_NOT_FOUND_MESSAGE) + ); + if (customer.getChatId() != null) { + notificationService.sendToUserBookingSuccessful(customer.getChatId(), savedBookingDto); + } notificationService.bookingsCreatedMessage(savedBookingDto); return savedBookingDto; } From 86782e110d9f0e59a94666ef16fa9501beabf67b Mon Sep 17 00:00:00 2001 From: Igor Korolevich Date: Tue, 16 Jan 2024 14:44:19 +0200 Subject: [PATCH 08/13] fix style --- src/main/java/com/application/bookingservice/model/Customer.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/application/bookingservice/model/Customer.java b/src/main/java/com/application/bookingservice/model/Customer.java index 23852b4..5e3b2db 100644 --- a/src/main/java/com/application/bookingservice/model/Customer.java +++ b/src/main/java/com/application/bookingservice/model/Customer.java @@ -51,6 +51,7 @@ public class Customer implements UserDetails { private Long chatId; @Column(name = "is_deleted", nullable = false) private Boolean isDeleted = false; + @Override public Collection getAuthorities() { return roles; From fd0321b51b398dceaa96833749127cb686a9eb5f Mon Sep 17 00:00:00 2001 From: Igor Korolevich Date: Tue, 16 Jan 2024 14:44:51 +0200 Subject: [PATCH 09/13] added send text to user and users --- .../bookingservice/bot/NotificationBot.java | 29 +++++++++++-------- .../service/bot/NotificationService.java | 2 +- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/application/bookingservice/bot/NotificationBot.java b/src/main/java/com/application/bookingservice/bot/NotificationBot.java index 35297df..47c67cb 100644 --- a/src/main/java/com/application/bookingservice/bot/NotificationBot.java +++ b/src/main/java/com/application/bookingservice/bot/NotificationBot.java @@ -5,6 +5,9 @@ import com.application.bookingservice.model.Customer; import com.application.bookingservice.repository.customer.CustomerRepository; import jakarta.persistence.EntityNotFoundException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -14,9 +17,6 @@ import org.telegram.telegrambots.meta.api.methods.updatingmessages.DeleteMessage; import org.telegram.telegrambots.meta.api.objects.Update; import org.telegram.telegrambots.meta.exceptions.TelegramApiException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; @Component public class NotificationBot extends TelegramLongPollingBot { @@ -27,7 +27,9 @@ public class NotificationBot extends TelegramLongPollingBot { private static final String CANT_LOG_MESSAGE = "Can't send logs to chat text: %s"; private static final String CANT_SEND_MESSAGE = "Can't send message to user chatId: %d"; private static final String START_MESSAGE = "hello im BINOV_booking_bot use /auth command " - + "if you haven't done it yet to receive notification or /cancel to stop receive messages"; + + "if you haven't done it yet to receive notification " + + "or /cancel to stop receive messages"; + private static final String DELETE_MESSAGE = "Can't delete user message"; private final String botName; private final CustomerRepository customerRepository; private CustomerLoginRequestDto requestDto; @@ -60,14 +62,13 @@ public String getBotUsername() { @Override public void onUpdateReceived(Update update) { - sendTextMessageToAll(update.getMessage().getText()); Long chatId = update.getMessage().getChatId(); AuthState currentState = authStates.getOrDefault(chatId, AuthState.STARTED); String recivedText = update.getMessage().getText(); if (recivedText.equals(START_COMMAND)) { handleStartCommand(update); } else if (authStates.containsKey(chatId)) { - authProcess(currentState, chatId, update); + authProcess(currentState, chatId, update); } else if (recivedText.equals(AUTH_COMMAND)) { sendTextMessage(chatId, "Please enter your login:"); authStates.put(chatId, AuthState.LOGIN); @@ -105,8 +106,9 @@ private void authProcess(AuthState currentState, Long chatId, Update update) { authenticationManager.authenticate(new UsernamePasswordAuthenticationToken( requestDto.getEmail(), requestDto.getPassword() )); - Customer customer = customerRepository.findByEmail(requestDto.getEmail()).orElseThrow( - () -> new EntityNotFoundException("Can't find customer") + Customer customer = customerRepository.findByEmail( + requestDto.getEmail()).orElseThrow( + () -> new EntityNotFoundException("Can't find customer") ); customer.setChatId(chatId); customerRepository.save(customer); @@ -119,6 +121,9 @@ private void authProcess(AuthState currentState, Long chatId, Update update) { requestDto.setPassword(""); } break; + default: + authStates.put(chatId, AuthState.STARTED); + break; } } @@ -131,7 +136,7 @@ public void sendTextMessageToAll(String text) { public void sendTextMessage(long chatId, String text) { SendMessage message = new SendMessage(); - message.setChatId(chatId); + message.setChatId(chatId); message.setText(text); try { @@ -167,12 +172,12 @@ private void handleStartCommand(Update update) { private void deletePreviousMessage(Long chatId, Update update) { int messageId = update.getMessage().getMessageId(); DeleteMessage deleteMessage = new DeleteMessage(); - deleteMessage.setChatId(chatId); - deleteMessage.setMessageId(messageId); + deleteMessage.setChatId(chatId); + deleteMessage.setMessageId(messageId); try { execute(deleteMessage); } catch (TelegramApiException e) { - throw new TelegramMessageException("Can't delete user message", e); + throw new TelegramMessageException(DELETE_MESSAGE, e); } } diff --git a/src/main/java/com/application/bookingservice/service/bot/NotificationService.java b/src/main/java/com/application/bookingservice/service/bot/NotificationService.java index 853bc78..a48687d 100644 --- a/src/main/java/com/application/bookingservice/service/bot/NotificationService.java +++ b/src/main/java/com/application/bookingservice/service/bot/NotificationService.java @@ -25,7 +25,7 @@ public interface NotificationService { Boolean sendToUserPayment(Long chatId, Payment payment); - Boolean sendToUserNewAccommodation(Long chatId, AccommodationResponseDto responseDto); + Boolean sendToUserNewAccommodation(AccommodationResponseDto responseDto); Boolean sendToAllUsers(String text); } From 302c58f21490c3c2ace0ebee6d14a206595c7b01 Mon Sep 17 00:00:00 2001 From: Igor Korolevich Date: Tue, 16 Jan 2024 14:45:11 +0200 Subject: [PATCH 10/13] added send text about payment --- .../service/payment/PaymentServiceImpl.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/application/bookingservice/service/payment/PaymentServiceImpl.java b/src/main/java/com/application/bookingservice/service/payment/PaymentServiceImpl.java index 0779e8d..83e5677 100644 --- a/src/main/java/com/application/bookingservice/service/payment/PaymentServiceImpl.java +++ b/src/main/java/com/application/bookingservice/service/payment/PaymentServiceImpl.java @@ -6,6 +6,7 @@ import com.application.bookingservice.exception.EntityNotFoundException; import com.application.bookingservice.mapper.PaymentMapper; import com.application.bookingservice.model.Booking; +import com.application.bookingservice.model.Customer; import com.application.bookingservice.model.Payment; import com.application.bookingservice.repository.booking.BookingRepository; import com.application.bookingservice.repository.payment.PaymentRepository; @@ -44,7 +45,10 @@ public void succeed(String sessionId) { Booking booking = payment.getBooking(); booking.setStatus(Booking.Status.CONFIRMED); bookingRepository.save(booking); - + Customer customer = booking.getCustomer(); + if (customer.getChatId() != null) { + notificationService.sendToUserPayment(customer.getChatId(), payment); + } notificationService.paymentMessage(payment); } @@ -60,7 +64,10 @@ public void cancel(String sessionId) { Booking booking = payment.getBooking(); booking.setStatus(Booking.Status.REJECTED); bookingRepository.save(booking); - + Customer customer = booking.getCustomer(); + if (customer.getChatId() != null) { + notificationService.sendToUserPayment(customer.getChatId(), payment); + } notificationService.paymentMessage(payment); } } From 591e16fea52c4bec069f0f528fce1156b420b978 Mon Sep 17 00:00:00 2001 From: Igor Korolevich Date: Tue, 16 Jan 2024 14:45:33 +0200 Subject: [PATCH 11/13] added controller to send personal message --- .../controller/BotController.java | 31 +++++++++++++++++++ .../bookingservice/dto/bot/BotRequestDto.java | 10 ++++++ 2 files changed, 41 insertions(+) create mode 100644 src/main/java/com/application/bookingservice/controller/BotController.java create mode 100644 src/main/java/com/application/bookingservice/dto/bot/BotRequestDto.java diff --git a/src/main/java/com/application/bookingservice/controller/BotController.java b/src/main/java/com/application/bookingservice/controller/BotController.java new file mode 100644 index 0000000..52107df --- /dev/null +++ b/src/main/java/com/application/bookingservice/controller/BotController.java @@ -0,0 +1,31 @@ +package com.application.bookingservice.controller; + +import com.application.bookingservice.dto.bot.BotRequestDto; +import com.application.bookingservice.service.bot.NotificationService; +import io.swagger.v3.oas.annotations.Operation; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/telegram") +public class BotController { + private final NotificationService notificationService; + + @PreAuthorize("hasRole('ROLE_MANAGER')") + @PostMapping + @ResponseStatus(HttpStatus.OK) + @Operation(summary = "Send notification", + description = "Permits to send message to all users") + public void sendNotification(@RequestBody @Valid BotRequestDto botRequestDto) { + notificationService.sendToAllUsers(botRequestDto.getMessage()); + } + +} diff --git a/src/main/java/com/application/bookingservice/dto/bot/BotRequestDto.java b/src/main/java/com/application/bookingservice/dto/bot/BotRequestDto.java new file mode 100644 index 0000000..8dd9637 --- /dev/null +++ b/src/main/java/com/application/bookingservice/dto/bot/BotRequestDto.java @@ -0,0 +1,10 @@ +package com.application.bookingservice.dto.bot; + +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class BotRequestDto { + @NotBlank + private String message; +} From 3530637e05b41c370a1e1fb1669083137af65003 Mon Sep 17 00:00:00 2001 From: Igor Korolevich Date: Tue, 16 Jan 2024 14:45:43 +0200 Subject: [PATCH 12/13] fix style --- .../bot/TelegramNotificationService.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/application/bookingservice/service/bot/TelegramNotificationService.java b/src/main/java/com/application/bookingservice/service/bot/TelegramNotificationService.java index 10ef013..3470830 100644 --- a/src/main/java/com/application/bookingservice/service/bot/TelegramNotificationService.java +++ b/src/main/java/com/application/bookingservice/service/bot/TelegramNotificationService.java @@ -156,11 +156,11 @@ public Boolean bookingExpiredMessage(String text) { @Override public Boolean sendToUserBookingSuccessful(Long chatId, BookingResponseDto responseDto) { StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(" Dear user your booking was successful \n you check in data: ") + stringBuilder.append("Dear user your booking was successful \n you check in data: ") .append(responseDto.getCheckIn()) - .append(" \nyour check out date :") + .append("\nyour check out date :") .append(responseDto.getCheckOut()) - .append("\n Thanks for picking BINOVO_booking!"); + .append("\nThanks for picking BINOVO_booking!"); notificationBot.sendTextMessage(chatId, stringBuilder.toString()); return true; } @@ -168,25 +168,25 @@ public Boolean sendToUserBookingSuccessful(Long chatId, BookingResponseDto respo @Override public Boolean sendToUserPayment(Long chatId, Payment payment) { StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(" Dear user your payment was ") + stringBuilder.append(" Dear user your payment was ") .append(payment.getStatus()) - .append("\n total :") + .append("\ntotal :") .append(payment.getTotal()) - .append("\n Thanks for picking BINOVO_booking!"); + .append("\nThanks for picking BINOVO_booking!"); notificationBot.sendTextMessage(chatId, stringBuilder.toString()); return true; } @Override - public Boolean sendToUserNewAccommodation(Long chatId, AccommodationResponseDto responseDto) { + public Boolean sendToUserNewAccommodation(AccommodationResponseDto responseDto) { StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(" Dear user we added new accommodation \n address: ") + stringBuilder.append("Dear users we added new accommodation \naddress: ") .append(responseDto.getAddress()) - .append("\n type: ") + .append("\ntype: ") .append(responseDto.getType()) - .append("\n best price :") + .append("\nbest price :") .append(responseDto.getPrice()); - notificationBot.sendTextMessage(chatId, stringBuilder.toString()); + notificationBot.sendTextMessageToAll(stringBuilder.toString()); return true; } From fa5e4bcd2ccf357a72e12863d52564789410bd7d Mon Sep 17 00:00:00 2001 From: Igor Korolevich Date: Tue, 16 Jan 2024 17:30:49 +0200 Subject: [PATCH 13/13] quick fix --- .../bookingservice/service/booking/BookingServiceImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/application/bookingservice/service/booking/BookingServiceImpl.java b/src/main/java/com/application/bookingservice/service/booking/BookingServiceImpl.java index 1cc3f3e..da0ef90 100644 --- a/src/main/java/com/application/bookingservice/service/booking/BookingServiceImpl.java +++ b/src/main/java/com/application/bookingservice/service/booking/BookingServiceImpl.java @@ -169,8 +169,8 @@ private void checkBookingDate() { LocalDate nowDate = LocalDate.now(); List bookings = bookingRepository.findAll(); for (Booking booking : bookings) { - if (booking.getCheckOut().isAfter(nowDate) - || booking.getCheckOut().isEqual(nowDate)) { + if ((booking.getCheckOut().isAfter(nowDate) + || booking.getCheckOut().isEqual(nowDate)) && booking.getStatus() != EXPIRED) { booking.setStatus(EXPIRED); bookingRepository.save(booking); expired = true;