Terminal BAEL-6520: Implement Telegram Bot using Spring-boot (#14595)

This commit is contained in:
Harry9656
2023-08-22 17:58:22 +02:00
committed by GitHub
parent 93988220ea
commit 11c984b995
9 changed files with 330 additions and 0 deletions
@@ -0,0 +1,9 @@
package com.baeldung.telegram;
public class Constants {
public static final String START_DESCRIPTION = "Starts the bot";
public static final String CHAT_STATES = "chatStates";
public static final String START_TEXT = "Welcome to Baeldung Pizza Bot.\nPlease enter your name";
}
@@ -0,0 +1,30 @@
package com.baeldung.telegram;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboard;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboardMarkup;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.KeyboardRow;
import java.util.List;
public class KeyboardFactory {
public static ReplyKeyboard getPizzaToppingsKeyboard() {
KeyboardRow row = new KeyboardRow();
row.add("Margherita");
row.add("Pepperoni");
return new ReplyKeyboardMarkup(List.of(row));
}
public static ReplyKeyboard getPizzaOrDrinkKeyboard(){
KeyboardRow row = new KeyboardRow();
row.add("Pizza");
row.add("Drink");
return new ReplyKeyboardMarkup(List.of(row));
}
public static ReplyKeyboard getYesOrNo() {
KeyboardRow row = new KeyboardRow();
row.add("Yes");
row.add("No");
return new ReplyKeyboardMarkup(List.of(row));
}
}
@@ -0,0 +1,48 @@
package com.baeldung.telegram;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.telegram.abilitybots.api.bot.AbilityBot;
import org.telegram.abilitybots.api.bot.BaseAbilityBot;
import org.telegram.abilitybots.api.objects.Ability;
import org.telegram.abilitybots.api.objects.Flag;
import org.telegram.abilitybots.api.objects.Reply;
import org.telegram.telegrambots.meta.api.objects.Update;
import java.util.function.BiConsumer;
import static org.telegram.abilitybots.api.objects.Locality.USER;
import static org.telegram.abilitybots.api.objects.Privacy.PUBLIC;
import static org.telegram.abilitybots.api.util.AbilityUtils.getChatId;
@Component
public class PizzaBot extends AbilityBot {
private final ResponseHandler responseHandler;
public PizzaBot(Environment environment) {
super(environment.getProperty("BOT_TOKEN"), "baeldungbot");
responseHandler = new ResponseHandler(silent, db);
}
public Ability startBot() {
return Ability
.builder()
.name("start")
.info(Constants.START_DESCRIPTION)
.locality(USER)
.privacy(PUBLIC)
.action(ctx -> responseHandler.replyToStart(ctx.chatId()))
.build();
}
public Reply replyToButtons() {
BiConsumer<BaseAbilityBot, Update> action = (abilityBot, upd) -> responseHandler.replyToButtons(getChatId(upd), upd.getMessage());
return Reply.of(action, Flag.TEXT,upd -> responseHandler.userIsActive(getChatId(upd)));
}
@Override
public long creatorId() {
return 1L;
}
}
@@ -0,0 +1,132 @@
package com.baeldung.telegram;
import org.telegram.abilitybots.api.db.DBContext;
import org.telegram.abilitybots.api.sender.SilentSender;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboard;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboardRemove;
import java.util.Map;
import static com.baeldung.telegram.Constants.START_TEXT;
import static com.baeldung.telegram.UserState.*;
public class ResponseHandler {
private final SilentSender sender;
private final Map<Long, UserState> chatStates;
public ResponseHandler(SilentSender sender, DBContext db) {
this.sender = sender;
chatStates = db.getMap(Constants.CHAT_STATES);
}
public void replyToStart(long chatId) {
SendMessage message = new SendMessage();
message.setChatId(chatId);
message.setText(START_TEXT);
sender.execute(message);
chatStates.put(chatId, AWAITING_NAME);
}
public void replyToButtons(long chatId, Message message) {
if (message.getText().equalsIgnoreCase("/stop")) {
stopChat(chatId);
}
switch (chatStates.get(chatId)) {
case AWAITING_NAME -> replyToName(chatId, message);
case FOOD_DRINK_SELECTION -> replyToFoodDrinkSelection(chatId, message);
case PIZZA_TOPPINGS -> replyToPizzaToppings(chatId, message);
case AWAITING_CONFIRMATION -> replyToOrder(chatId, message);
default -> unexpectedMessage(chatId);
}
}
private void unexpectedMessage(long chatId) {
SendMessage sendMessage = new SendMessage();
sendMessage.setChatId(chatId);
sendMessage.setText("I did not expect that.");
sender.execute(sendMessage);
}
private void stopChat(long chatId) {
SendMessage sendMessage = new SendMessage();
sendMessage.setChatId(chatId);
sendMessage.setText("Thank you for your order. See you soon!\nPress /start to order again");
chatStates.remove(chatId);
sendMessage.setReplyMarkup(new ReplyKeyboardRemove(true));
sender.execute(sendMessage);
}
private void replyToOrder(long chatId, Message message) {
SendMessage sendMessage = new SendMessage();
sendMessage.setChatId(chatId);
if ("yes".equalsIgnoreCase(message.getText())) {
sendMessage.setText("We will deliver it soon. Thank you!\nOrder another?");
sendMessage.setReplyMarkup(KeyboardFactory.getPizzaOrDrinkKeyboard());
sender.execute(sendMessage);
chatStates.put(chatId, FOOD_DRINK_SELECTION);
} else if ("no".equalsIgnoreCase(message.getText())) {
stopChat(chatId);
} else {
sendMessage.setText("Please select yes or no");
sendMessage.setReplyMarkup(KeyboardFactory.getYesOrNo());
sender.execute(sendMessage);
}
}
private void replyToPizzaToppings(long chatId, Message message) {
if ("margherita".equalsIgnoreCase(message.getText())) {
promptWithKeyboardForState(chatId, "You selected Margherita Pizza.\nWe will deliver it soon. Thank you!\nOrder again?",
KeyboardFactory.getYesOrNo(), AWAITING_CONFIRMATION);
} else if ("pepperoni".equalsIgnoreCase(message.getText())) {
promptWithKeyboardForState(chatId, "We finished the Pepperoni Pizza.\nSelect another Topping",
KeyboardFactory.getPizzaToppingsKeyboard(), PIZZA_TOPPINGS);
} else {
SendMessage sendMessage = new SendMessage();
sendMessage.setChatId(chatId);
sendMessage.setText("We don't sell " + message.getText() + " Pizza.\nSelect the toppings!");
sendMessage.setReplyMarkup(KeyboardFactory.getPizzaToppingsKeyboard());
sender.execute(sendMessage);
}
}
private void promptWithKeyboardForState(long chatId, String text, ReplyKeyboard YesOrNo, UserState awaitingReorder) {
SendMessage sendMessage = new SendMessage();
sendMessage.setChatId(chatId);
sendMessage.setText(text);
sendMessage.setReplyMarkup(YesOrNo);
sender.execute(sendMessage);
chatStates.put(chatId, awaitingReorder);
}
private void replyToFoodDrinkSelection(long chatId, Message message) {
SendMessage sendMessage = new SendMessage();
sendMessage.setChatId(chatId);
if ("drink".equalsIgnoreCase(message.getText())) {
sendMessage.setText("We don't sell drinks.\nBring your own drink!! :)");
sendMessage.setReplyMarkup(KeyboardFactory.getPizzaOrDrinkKeyboard());
sender.execute(sendMessage);
} else if ("pizza".equalsIgnoreCase(message.getText())) {
sendMessage.setText("We love Pizza in here.\nSelect the toppings!");
sendMessage.setReplyMarkup(KeyboardFactory.getPizzaToppingsKeyboard());
sender.execute(sendMessage);
chatStates.put(chatId, UserState.PIZZA_TOPPINGS);
} else {
sendMessage.setText("We don't sell " + message.getText() + ". Please select from the options below.");
sendMessage.setReplyMarkup(KeyboardFactory.getPizzaOrDrinkKeyboard());
sender.execute(sendMessage);
}
}
private void replyToName(long chatId, Message message) {
promptWithKeyboardForState(chatId, "Hello " + message.getText() + ". What would you like to have?",
KeyboardFactory.getPizzaOrDrinkKeyboard(),
UserState.FOOD_DRINK_SELECTION);
}
public boolean userIsActive(Long chatId) {
return chatStates.containsKey(chatId);
}
}
@@ -0,0 +1,24 @@
package com.baeldung.telegram;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.telegram.abilitybots.api.bot.AbilityBot;
import org.telegram.telegrambots.meta.TelegramBotsApi;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import org.telegram.telegrambots.updatesreceivers.DefaultBotSession;
@SpringBootApplication
public class SpringBootTelegramApplication {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(SpringBootTelegramApplication.class, args);
try {
TelegramBotsApi botsApi = new TelegramBotsApi(DefaultBotSession.class);
botsApi.registerBot(ctx.getBean("pizzaBot", AbilityBot.class));
} catch (TelegramApiException e) {
throw new RuntimeException(e);
}
}
}
@@ -0,0 +1,5 @@
package com.baeldung.telegram;
public enum UserState {
AWAITING_NAME, FOOD_DRINK_SELECTION, PIZZA_TOPPINGS, AWAITING_CONFIRMATION
}
@@ -0,0 +1,2 @@
server.port=8081
BOT_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX