From d6ef3c06928c6d7fab33fc4635448152a9f882d7 Mon Sep 17 00:00:00 2001 From: Oleksandr <145048428+OleksandrRym@users.noreply.github.com> Date: Sat, 23 Nov 2024 09:43:11 -0800 Subject: [PATCH] feature/TRAC-6 (#8) * [TRAC-6] - Implement Message Service and basic Command Handling * [TRAC-6] - Implement Message Service and basic Command Handling * [TRAC-6] - Implement Message Service and basic Command Handling --- .../adaptors/persistence/package-info.java | 4 +-- .../adaptors/telegram/TelegramBotClient.java | 13 ++++++++ .../telegram/TelegramBotConsumer.java | 4 +++ .../trackmycoin/command/Command.java | 15 +++++++++ .../command/CommandProcessorRegistry.java | 33 +++++++++++++++++++ .../command/processor/CommandProcessor.java | 11 +++++++ .../command/processor/HelpCommandProcess.java | 28 ++++++++++++++++ .../processor/InfoCommandProcessor.java | 28 ++++++++++++++++ .../processor/NonCommandProcessor.java | 27 +++++++++++++++ .../processor/StartCommandProcessor.java | 28 ++++++++++++++++ .../config/TelegramBotDescription.java | 19 +++++++++++ .../trackmycoin/domain/package-info.java | 5 +-- .../trackmycoin/service/package-info.java | 4 +-- src/main/resources/application.yml | 17 +++++++++- 14 files changed, 227 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/Command.java create mode 100644 src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/CommandProcessorRegistry.java create mode 100644 src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/processor/CommandProcessor.java create mode 100644 src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/processor/HelpCommandProcess.java create mode 100644 src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/processor/InfoCommandProcessor.java create mode 100644 src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/processor/NonCommandProcessor.java create mode 100644 src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/processor/StartCommandProcessor.java create mode 100644 src/main/java/com/vladyslavpalamarchuk/trackmycoin/config/TelegramBotDescription.java diff --git a/src/main/java/com/vladyslavpalamarchuk/trackmycoin/adaptors/persistence/package-info.java b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/adaptors/persistence/package-info.java index 932fb71..dd23e31 100644 --- a/src/main/java/com/vladyslavpalamarchuk/trackmycoin/adaptors/persistence/package-info.java +++ b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/adaptors/persistence/package-info.java @@ -1,5 +1,5 @@ /** - * This package contains persistence config for application - * TODO delete this file after adding new files + * This package contains persistence config for application TODO delete this file after adding new + * files */ package com.vladyslavpalamarchuk.trackmycoin.adaptors.persistence; diff --git a/src/main/java/com/vladyslavpalamarchuk/trackmycoin/adaptors/telegram/TelegramBotClient.java b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/adaptors/telegram/TelegramBotClient.java index 0ba84d4..4f2b0b9 100644 --- a/src/main/java/com/vladyslavpalamarchuk/trackmycoin/adaptors/telegram/TelegramBotClient.java +++ b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/adaptors/telegram/TelegramBotClient.java @@ -1,12 +1,25 @@ package com.vladyslavpalamarchuk.trackmycoin.adaptors.telegram; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import org.telegram.telegrambots.meta.api.methods.send.SendMessage; +import org.telegram.telegrambots.meta.exceptions.TelegramApiException; import org.telegram.telegrambots.meta.generics.TelegramClient; +@Slf4j @Component @RequiredArgsConstructor public class TelegramBotClient { private final TelegramClient telegramClient; + + public void sendMessage(Long chatId, String messageText) { + SendMessage message = SendMessage.builder().chatId(chatId).text(messageText).build(); + try { + telegramClient.execute(message); + } catch (TelegramApiException e) { + log.error("Fail to send telegram message to chatId: {}", chatId, e); + } + } } diff --git a/src/main/java/com/vladyslavpalamarchuk/trackmycoin/adaptors/telegram/TelegramBotConsumer.java b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/adaptors/telegram/TelegramBotConsumer.java index bfd234b..3ee5a27 100644 --- a/src/main/java/com/vladyslavpalamarchuk/trackmycoin/adaptors/telegram/TelegramBotConsumer.java +++ b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/adaptors/telegram/TelegramBotConsumer.java @@ -1,5 +1,6 @@ package com.vladyslavpalamarchuk.trackmycoin.adaptors.telegram; +import com.vladyslavpalamarchuk.trackmycoin.command.CommandProcessorRegistry; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -12,10 +13,13 @@ @RequiredArgsConstructor public class TelegramBotConsumer implements LongPollingSingleThreadUpdateConsumer { + private final CommandProcessorRegistry commandProcessorRegistry; + @Override public void consume(Update update) { if (update.hasMessage() && update.getMessage().hasText()) { logUpdateMessage(update.getMessage()); + commandProcessorRegistry.get(update.getMessage().getText()).process(update); } } diff --git a/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/Command.java b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/Command.java new file mode 100644 index 0000000..783f2e5 --- /dev/null +++ b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/Command.java @@ -0,0 +1,15 @@ +package com.vladyslavpalamarchuk.trackmycoin.command; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum Command { + START("/start"), + INFO("/info"), + HELP("/help"), + NON_COMMAND(""); + + private final String command; +} diff --git a/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/CommandProcessorRegistry.java b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/CommandProcessorRegistry.java new file mode 100644 index 0000000..d17926f --- /dev/null +++ b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/CommandProcessorRegistry.java @@ -0,0 +1,33 @@ +package com.vladyslavpalamarchuk.trackmycoin.command; + +import com.vladyslavpalamarchuk.trackmycoin.command.processor.CommandProcessor; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.springframework.stereotype.Service; + +@Service +public class CommandProcessorRegistry { + + private final Map commandToProcessors; + + public CommandProcessorRegistry(List processors) { + commandToProcessors = + processors.stream() + .collect(Collectors.toMap(CommandProcessor::getCommand, Function.identity())); + } + + public CommandProcessor get(String messageText) { + if (!messageText.startsWith("/")) { + return commandToProcessors.get(Command.NON_COMMAND); + } + + return Arrays.stream(Command.values()) + .filter(c -> c.getCommand().equalsIgnoreCase(messageText)) + .findFirst() + .map(commandToProcessors::get) + .orElse(commandToProcessors.get(Command.NON_COMMAND)); + } +} diff --git a/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/processor/CommandProcessor.java b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/processor/CommandProcessor.java new file mode 100644 index 0000000..5af27c6 --- /dev/null +++ b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/processor/CommandProcessor.java @@ -0,0 +1,11 @@ +package com.vladyslavpalamarchuk.trackmycoin.command.processor; + +import com.vladyslavpalamarchuk.trackmycoin.command.Command; +import org.telegram.telegrambots.meta.api.objects.Update; + +public interface CommandProcessor { + + void process(Update update); + + Command getCommand(); +} diff --git a/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/processor/HelpCommandProcess.java b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/processor/HelpCommandProcess.java new file mode 100644 index 0000000..6eee781 --- /dev/null +++ b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/processor/HelpCommandProcess.java @@ -0,0 +1,28 @@ +package com.vladyslavpalamarchuk.trackmycoin.command.processor; + +import com.vladyslavpalamarchuk.trackmycoin.adaptors.telegram.TelegramBotClient; +import com.vladyslavpalamarchuk.trackmycoin.command.Command; +import com.vladyslavpalamarchuk.trackmycoin.config.TelegramBotDescription; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.telegram.telegrambots.meta.api.objects.Update; + +@Component +@RequiredArgsConstructor +public class HelpCommandProcess implements CommandProcessor { + + private final TelegramBotClient telegramBotClient; + + private final TelegramBotDescription telegramBotDescription; + + @Override + public void process(Update update) { + telegramBotClient.sendMessage( + update.getMessage().getChatId(), telegramBotDescription.getHelp()); + } + + @Override + public Command getCommand() { + return Command.HELP; + } +} diff --git a/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/processor/InfoCommandProcessor.java b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/processor/InfoCommandProcessor.java new file mode 100644 index 0000000..dcd1232 --- /dev/null +++ b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/processor/InfoCommandProcessor.java @@ -0,0 +1,28 @@ +package com.vladyslavpalamarchuk.trackmycoin.command.processor; + +import com.vladyslavpalamarchuk.trackmycoin.adaptors.telegram.TelegramBotClient; +import com.vladyslavpalamarchuk.trackmycoin.command.Command; +import com.vladyslavpalamarchuk.trackmycoin.config.TelegramBotDescription; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.telegram.telegrambots.meta.api.objects.Update; + +@Component +@RequiredArgsConstructor +public class InfoCommandProcessor implements CommandProcessor { + + private final TelegramBotClient telegramBotClient; + + private final TelegramBotDescription telegramBotDescription; + + @Override + public void process(Update update) { + telegramBotClient.sendMessage( + update.getMessage().getChatId(), telegramBotDescription.getInfo()); + } + + @Override + public Command getCommand() { + return Command.INFO; + } +} diff --git a/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/processor/NonCommandProcessor.java b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/processor/NonCommandProcessor.java new file mode 100644 index 0000000..91405ce --- /dev/null +++ b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/processor/NonCommandProcessor.java @@ -0,0 +1,27 @@ +package com.vladyslavpalamarchuk.trackmycoin.command.processor; + +import com.vladyslavpalamarchuk.trackmycoin.adaptors.telegram.TelegramBotClient; +import com.vladyslavpalamarchuk.trackmycoin.command.Command; +import com.vladyslavpalamarchuk.trackmycoin.config.TelegramBotDescription; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.telegram.telegrambots.meta.api.objects.Update; + +@Component +@RequiredArgsConstructor +public class NonCommandProcessor implements CommandProcessor { + private final TelegramBotClient telegramBotClient; + + private final TelegramBotDescription telegramBotDescription; + + @Override + public void process(Update update) { + telegramBotClient.sendMessage( + update.getMessage().getChatId(), telegramBotDescription.getNonCommand()); + } + + @Override + public Command getCommand() { + return Command.NON_COMMAND; + } +} diff --git a/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/processor/StartCommandProcessor.java b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/processor/StartCommandProcessor.java new file mode 100644 index 0000000..f0dcc8a --- /dev/null +++ b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/command/processor/StartCommandProcessor.java @@ -0,0 +1,28 @@ +package com.vladyslavpalamarchuk.trackmycoin.command.processor; + +import com.vladyslavpalamarchuk.trackmycoin.adaptors.telegram.TelegramBotClient; +import com.vladyslavpalamarchuk.trackmycoin.command.Command; +import com.vladyslavpalamarchuk.trackmycoin.config.TelegramBotDescription; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.telegram.telegrambots.meta.api.objects.Update; + +@Component +@RequiredArgsConstructor +public class StartCommandProcessor implements CommandProcessor { + + private final TelegramBotClient telegramBotClient; + + private final TelegramBotDescription telegramBotDescription; + + @Override + public void process(Update update) { + telegramBotClient.sendMessage( + update.getMessage().getChatId(), telegramBotDescription.getStart()); + } + + @Override + public Command getCommand() { + return Command.START; + } +} diff --git a/src/main/java/com/vladyslavpalamarchuk/trackmycoin/config/TelegramBotDescription.java b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/config/TelegramBotDescription.java new file mode 100644 index 0000000..7284dd5 --- /dev/null +++ b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/config/TelegramBotDescription.java @@ -0,0 +1,19 @@ +package com.vladyslavpalamarchuk.trackmycoin.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Data +@Component +@ConfigurationProperties(prefix = "description") +public class TelegramBotDescription { + + private String start; + + private String info; + + private String help; + + private String nonCommand; +} diff --git a/src/main/java/com/vladyslavpalamarchuk/trackmycoin/domain/package-info.java b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/domain/package-info.java index 38fff6f..8b02d69 100644 --- a/src/main/java/com/vladyslavpalamarchuk/trackmycoin/domain/package-info.java +++ b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/domain/package-info.java @@ -1,5 +1,2 @@ -/** - * This package contains domain entities - * TODO delete this file after adding new files - */ +/** This package contains domain entities TODO delete this file after adding new files */ package com.vladyslavpalamarchuk.trackmycoin.domain; diff --git a/src/main/java/com/vladyslavpalamarchuk/trackmycoin/service/package-info.java b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/service/package-info.java index 7d59657..c7c74f5 100644 --- a/src/main/java/com/vladyslavpalamarchuk/trackmycoin/service/package-info.java +++ b/src/main/java/com/vladyslavpalamarchuk/trackmycoin/service/package-info.java @@ -1,5 +1,5 @@ /** - * This package contains business logic of the application - * TODO delete this file after adding new files + * This package contains business logic of the application TODO delete this file after adding new + * files */ package com.vladyslavpalamarchuk.trackmycoin.service; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 31b5174..38d0935 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -7,4 +7,19 @@ spring: url: ${POSTGRESQL_JDBC_URL} username: ${POSTGRESQL_USERNAME} password: ${POSTGRESQL_PASSWORD} - driver-class-name: org.postgresql.Driver \ No newline at end of file + driver-class-name: org.postgresql.Driver +description: + start: "Welcome to TrackMyCoin 📈💰! + \n\nThis bot helps you track cryptocurrency prices + and will send you notifications when your target price + is reached. + \n\nFor more information about the bot, type /info." + info: "TrackMyCoin — your crypto assistant 📈💰! + + \nEasily track cryptocurrency prices and get notified + when your target price is reached. + \nPerfect for traders and crypto enthusiasts! + + \nType /help for a list of all commands." + help: "List of commands 👾\nInfo -> /info\nHelp -> /help" + non_command: "non command /help " \ No newline at end of file