Telegram Bot Java自定义计算器键盘 实现完整数字输入后发送消息问询
解决Telegram Bot数字键盘输入完整数字后再发送的问题
嘿,我懂你的困扰——现在每次点数字按钮都会直接发一条单独的消息,想输入1000却连发四条消息,完全不是想要的效果对吧?其实核心思路就是给每个用户维护一个临时的输入缓冲区,把点击的数字先存起来,等用户确认发送的时候再一次性提交。下面是具体的实现方案,适配你用的Java Telegram Bot API:
一、核心思路拆解
- 用户输入隔离:每个用户的输入是独立的,用一个Map来存储每个用户ID对应的当前输入字符串。
- 键盘扩展:在原有数字键盘基础上添加「发送」和「清空」按钮,让用户能主动触发提交或重置操作。
- 按钮点击逻辑重写:数字按钮不再直接发送消息,而是追加到缓冲区;功能按钮负责提交或清空缓冲区内容。
二、完整代码实现
1. 定义全局输入缓冲区
首先需要一个线程安全的Map来存储用户的临时输入,避免多用户操作时出现冲突:
// 用ConcurrentHashMap保证线程安全,key是用户的ChatId,value是当前输入的数字字符串 private Map<Long, String> userInputBuffer = new ConcurrentHashMap<>();
2. 重构键盘布局
给数字键盘添加功能按钮行,方便用户操作:
ReplyKeyboardMarkup keyBoardMarkup = new ReplyKeyboardMarkup(); keyBoardMarkup.setResizeKeyboard(true); // 让键盘自适应屏幕大小 List<KeyboardRow> keyboard = new ArrayList<>(); // 第一行:1、2、3 KeyboardRow row1 = new KeyboardRow(); row1.add("1"); row1.add("2"); row1.add("3"); keyboard.add(row1); // 第二行:4、5、6 KeyboardRow row2 = new KeyboardRow(); row2.add("4"); row2.add("5"); row2.add("6"); keyboard.add(row2); // 第三行:7、8、9 KeyboardRow row3 = new KeyboardRow(); row3.add("7"); row3.add("8"); row3.add("9"); keyboard.add(row3); // 第四行:0、清空、发送 KeyboardRow row4 = new KeyboardRow(); row4.add("0"); row4.add("清空"); row4.add("发送"); keyboard.add(row4); keyBoardMarkup.setKeyboard(keyboard);
3. 处理按钮点击逻辑
在消息处理方法里,判断用户点击的是数字还是功能按钮,执行对应的操作:
@Override public void onUpdateReceived(Update update) { if (update.hasMessage() && update.getMessage().hasText()) { Long userId = update.getMessage().getChatId(); String inputText = update.getMessage().getText(); // 处理数字按钮点击 if (inputText.matches("[0-9]")) { // 从缓冲区取出当前输入,没有则为空字符串 String currentInput = userInputBuffer.getOrDefault(userId, ""); // 追加新数字 currentInput += inputText; userInputBuffer.put(userId, currentInput); // 给用户反馈当前输入状态 sendReplyMessage(userId, "当前输入:" + currentInput, keyBoardMarkup); } // 处理清空按钮 else if (inputText.equals("清空")) { userInputBuffer.remove(userId); sendReplyMessage(userId, "已清空输入,请重新输入~", keyBoardMarkup); } // 处理发送按钮 else if (inputText.equals("发送")) { String fullNumber = userInputBuffer.getOrDefault(userId, ""); if (fullNumber.isEmpty()) { sendReplyMessage(userId, "还没输入数字哦,请先点击数字按钮~", keyBoardMarkup); } else { // 这里可以把完整数字发送到目标聊天,或者做后续处理 sendReplyMessage(userId, "你输入的完整数字是:*" + fullNumber + "*", keyBoardMarkup); // 发送完成后清空缓冲区 userInputBuffer.remove(userId); } } // 处理其他非键盘输入 else { sendReplyMessage(userId, "请使用下方的数字键盘输入哦", keyBoardMarkup); } } } // 封装发送消息的工具方法,避免重复代码 private void sendReplyMessage(Long chatId, String text, ReplyKeyboardMarkup keyboard) { SendMessage message = new SendMessage(); message.setChatId(chatId.toString()); message.setText(text); message.setParseMode(ParseMode.MARKDOWN); // 支持Markdown格式强调 message.setReplyMarkup(keyboard); try { execute(message); } catch (TelegramApiException e) { e.printStackTrace(); } }
三、额外优化建议
- 增加删除按钮:可以在键盘里加一个「删除」按钮,实现删除最后一位数字的功能,提升用户体验。
- 输入超时清理:如果用户长时间不操作,可以定时清理缓冲区里的无效输入,避免内存浪费。
- 分布式场景适配:如果你的Bot是多实例部署,ConcurrentHashMap就不够用了,建议用Redis等分布式存储来保存用户输入。
内容的提问来源于stack exchange,提问作者andron
相关产品推荐
相关产品推荐

