Terminal BAEL-6520: Implement Telegram Bot using Spring-boot (#14595)
This commit is contained in:
parent
93988220ea
commit
11c984b995
|
@ -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/
|
|
@ -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>
|
|
@ -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
|
Loading…
Reference in New Issue