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

View File

@ -0,0 +1,35 @@
HELP.md
target/
.mvn
mvnw
mvnw.cmd
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baelding</groupId>
<artifactId>spring-boot-telegram</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-telegram</name>
<description>Demo project for Spring Boot with Spring Data Redis</description>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-3</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.telegram</groupId>
<artifactId>telegrambots-spring-boot-starter</artifactId>
<version>6.7.0</version>
</dependency>
<dependency>
<groupId>org.telegram</groupId>
<artifactId>telegrambots-abilities</artifactId>
<version>6.7.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<properties>
<java.version>17</java.version>
</properties>
</project>

View File

@ -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";
}

View File

@ -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));
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -0,0 +1,5 @@
package com.baeldung.telegram;
public enum UserState {
AWAITING_NAME, FOOD_DRINK_SELECTION, PIZZA_TOPPINGS, AWAITING_CONFIRMATION
}

View File

@ -0,0 +1,2 @@
server.port=8081
BOT_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX