Merge branch 'implement_command_mechanism' of https://github.com/Mit0x2/TelegramBots into Mit0x2-implement_command_mechanism
This commit is contained in:
commit
480f9a6907
@ -126,7 +126,7 @@ public class TelegramBotsApi {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a bot. The Bot Session is started immediately, and may be disconnected by calling close.
|
* Register a bot. The Bot Session is started immediately, and may be disconnected by calling close.
|
||||||
* @param bot
|
* @param bot the bot to register
|
||||||
*/
|
*/
|
||||||
public BotSession registerBot(TelegramLongPollingBot bot) throws TelegramApiException {
|
public BotSession registerBot(TelegramLongPollingBot bot) throws TelegramApiException {
|
||||||
setWebhook(bot.getBotToken());
|
setWebhook(bot.getBotToken());
|
||||||
|
@ -0,0 +1,70 @@
|
|||||||
|
package org.telegram.telegrambots.api.commands;
|
||||||
|
|
||||||
|
import org.telegram.telegrambots.api.objects.Chat;
|
||||||
|
import org.telegram.telegrambots.bots.AbsSender;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation of a command, which can be executed
|
||||||
|
*
|
||||||
|
* @author tschulz
|
||||||
|
*/
|
||||||
|
public abstract class BotCommand {
|
||||||
|
|
||||||
|
public final static String COMMAND_INIT_CHARACTER = "/";
|
||||||
|
public final static String COMMAND_PARAMETER_SEPARATOR = " ";
|
||||||
|
private final static int COMMAND_MAX_LENGTH = 32;
|
||||||
|
|
||||||
|
private final String commandIdentifier;
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* construct a command
|
||||||
|
*
|
||||||
|
* @param commandIdentifier the unique identifier of this command (e.g. the command string to enter into chat)
|
||||||
|
* @param description the description of this command
|
||||||
|
*/
|
||||||
|
public BotCommand(String commandIdentifier, String description) {
|
||||||
|
|
||||||
|
if (commandIdentifier == null || commandIdentifier.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("commandIdentifier for command cannot be null or empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commandIdentifier.startsWith(COMMAND_INIT_CHARACTER)) {
|
||||||
|
commandIdentifier = commandIdentifier.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commandIdentifier.length() + 1 > COMMAND_MAX_LENGTH) {
|
||||||
|
throw new IllegalArgumentException("commandIdentifier cannot be longer than " + COMMAND_MAX_LENGTH + " (including " + COMMAND_INIT_CHARACTER + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.commandIdentifier = commandIdentifier.toLowerCase();
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the identifier of this command
|
||||||
|
*
|
||||||
|
* @return the identifier
|
||||||
|
*/
|
||||||
|
public final String getCommandIdentifier() {
|
||||||
|
return commandIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the description of this command
|
||||||
|
*
|
||||||
|
* @return the description as String
|
||||||
|
*/
|
||||||
|
public final String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* execute the command
|
||||||
|
*
|
||||||
|
* @param absSender absSender to send messages over
|
||||||
|
* @param chat the chat, to be able to send replies
|
||||||
|
* @param arguments passed arguments
|
||||||
|
*/
|
||||||
|
public abstract void execute(AbsSender absSender, Chat chat, String[] arguments);
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
package org.telegram.telegrambots.api.commands;
|
||||||
|
|
||||||
|
import org.telegram.telegrambots.api.objects.Message;
|
||||||
|
import org.telegram.telegrambots.bots.AbsSender;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tschulz
|
||||||
|
*/
|
||||||
|
public final class CommandRegistry implements ICommandRegistry {
|
||||||
|
|
||||||
|
private final Map<String, BotCommand> commandRegistryMap = new HashMap<>();
|
||||||
|
|
||||||
|
public CommandRegistry(String botToken) {
|
||||||
|
register(new HelpBotCommand(this, botToken));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final boolean register(BotCommand botCommand) {
|
||||||
|
if (commandRegistryMap.containsKey(botCommand.getCommandIdentifier())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
commandRegistryMap.put(botCommand.getCommandIdentifier(), botCommand);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Map<BotCommand, Boolean> registerAll(BotCommand... botCommands) {
|
||||||
|
Map<BotCommand, Boolean> resultMap = new HashMap<>(botCommands.length);
|
||||||
|
for (BotCommand botCommand : botCommands) {
|
||||||
|
resultMap.put(botCommand, register(botCommand));
|
||||||
|
}
|
||||||
|
return resultMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final boolean deregister(BotCommand botCommand) {
|
||||||
|
if (commandRegistryMap.containsKey(botCommand.getCommandIdentifier())) {
|
||||||
|
commandRegistryMap.remove(botCommand.getCommandIdentifier());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Map<BotCommand, Boolean> deregisterAll(BotCommand... botCommands) {
|
||||||
|
Map<BotCommand, Boolean> resultMap = new HashMap<>(botCommands.length);
|
||||||
|
for (BotCommand botCommand : botCommands) {
|
||||||
|
resultMap.put(botCommand, deregister(botCommand));
|
||||||
|
}
|
||||||
|
return resultMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Collection<BotCommand> getRegisteredCommands() {
|
||||||
|
return commandRegistryMap.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* executes a command if present and replies the success
|
||||||
|
*
|
||||||
|
* @param message input message
|
||||||
|
* @return true if success or false otherwise
|
||||||
|
*/
|
||||||
|
public final boolean executeCommand(AbsSender absSender, Message message) {
|
||||||
|
if (message.hasText()) {
|
||||||
|
String text = message.getText();
|
||||||
|
if (!text.isEmpty() && text.startsWith(BotCommand.COMMAND_INIT_CHARACTER)) {
|
||||||
|
String commandMessage = text.substring(1);
|
||||||
|
String[] commandSplit = commandMessage.split(BotCommand.COMMAND_PARAMETER_SEPARATOR);
|
||||||
|
|
||||||
|
String command = commandSplit[0];
|
||||||
|
|
||||||
|
if (commandRegistryMap.containsKey(command)) {
|
||||||
|
String[] parameters = Arrays.copyOfRange(commandSplit, 1, commandSplit.length);
|
||||||
|
commandRegistryMap.get(command).execute(absSender, message.getChat(), parameters);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package org.telegram.telegrambots.api.commands;
|
||||||
|
|
||||||
|
import org.telegram.telegrambots.TelegramApiException;
|
||||||
|
import org.telegram.telegrambots.api.methods.send.SendMessage;
|
||||||
|
import org.telegram.telegrambots.api.objects.Chat;
|
||||||
|
import org.telegram.telegrambots.bots.AbsSender;
|
||||||
|
import org.telegram.telegrambots.logging.BotLogger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* standard help command, which gets registered by default, to supply a list of all available commands
|
||||||
|
*
|
||||||
|
* @author tschulz
|
||||||
|
*/
|
||||||
|
public class HelpBotCommand extends BotCommand {
|
||||||
|
|
||||||
|
private static final String LOGTAG = "HELPCOMMAND";
|
||||||
|
private final ICommandRegistry commandRegistry;
|
||||||
|
|
||||||
|
public HelpBotCommand(ICommandRegistry commandRegistry, String botToken) {
|
||||||
|
super("help", "Gives an overview over all Commands registered for this bot");
|
||||||
|
this.commandRegistry = commandRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(AbsSender absSender, Chat chat, String[] arguments) {
|
||||||
|
|
||||||
|
for (BotCommand registeredBotCommand : commandRegistry.getRegisteredCommands()) {
|
||||||
|
SendMessage sendMessage = new SendMessage();
|
||||||
|
sendMessage.setChatId(chat.getId().toString());
|
||||||
|
sendMessage.enableHtml(true);
|
||||||
|
sendMessage.setText("<b>" + COMMAND_INIT_CHARACTER + registeredBotCommand.getCommandIdentifier() + "</b>\n" + registeredBotCommand.getDescription());
|
||||||
|
|
||||||
|
try {
|
||||||
|
absSender.sendMessage(sendMessage);
|
||||||
|
} catch (TelegramApiException e) {
|
||||||
|
BotLogger.error("Failed to send HelpMessage", LOGTAG, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package org.telegram.telegrambots.api.commands;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface ICommandRegistry {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* register a command
|
||||||
|
*
|
||||||
|
* @param botCommand the command to register
|
||||||
|
* @return whether the command could be registered, was not already registered
|
||||||
|
*/
|
||||||
|
boolean register(BotCommand botCommand);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* register multiple commands
|
||||||
|
*
|
||||||
|
* @param botCommands commands to register
|
||||||
|
* @return map with results of the command register per command
|
||||||
|
*/
|
||||||
|
Map<BotCommand, Boolean> registerAll(BotCommand... botCommands);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* deregister a command
|
||||||
|
*
|
||||||
|
* @param botCommand the command to deregister
|
||||||
|
* @return whether the command could be deregistered, was registered
|
||||||
|
*/
|
||||||
|
boolean deregister(BotCommand botCommand);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* deregister multiple commands
|
||||||
|
*
|
||||||
|
* @param botCommands commands to deregister
|
||||||
|
* @return map with results of the command deregistered per command
|
||||||
|
*/
|
||||||
|
Map<BotCommand, Boolean> deregisterAll(BotCommand... botCommands);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get a collection of all registered commands
|
||||||
|
*
|
||||||
|
* @return a collection of registered commands
|
||||||
|
*/
|
||||||
|
Collection<BotCommand> getRegisteredCommands();
|
||||||
|
|
||||||
|
}
|
@ -381,6 +381,17 @@ public class Message implements IBotApiObject {
|
|||||||
return text != null && !text.isEmpty();
|
return text != null && !text.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isCommand() {
|
||||||
|
if (entities != null) {
|
||||||
|
for (MessageEntity entity : entities) {
|
||||||
|
if (entity != null && "bot_command".equals(entity.getType())) {
|
||||||
|
return text != null && !text.isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasDocument() {
|
public boolean hasDocument() {
|
||||||
return this.document != null;
|
return this.document != null;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,88 @@
|
|||||||
|
package org.telegram.telegrambots.bots;
|
||||||
|
|
||||||
|
|
||||||
|
import org.telegram.telegrambots.TelegramApiException;
|
||||||
|
import org.telegram.telegrambots.api.commands.BotCommand;
|
||||||
|
import org.telegram.telegrambots.api.commands.CommandRegistry;
|
||||||
|
import org.telegram.telegrambots.api.commands.ICommandRegistry;
|
||||||
|
import org.telegram.telegrambots.api.methods.send.SendMessage;
|
||||||
|
import org.telegram.telegrambots.api.objects.Message;
|
||||||
|
import org.telegram.telegrambots.api.objects.Update;
|
||||||
|
import org.telegram.telegrambots.logging.BotLogger;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class adds command functionality to the TelegramLongPollingBot
|
||||||
|
*
|
||||||
|
* @author tschulz
|
||||||
|
*/
|
||||||
|
public abstract class TelegramLongPollingCommandBot extends TelegramLongPollingBot implements ICommandRegistry {
|
||||||
|
|
||||||
|
public static final String LOGTAG = "TelegramLongPollingCommandBot";
|
||||||
|
private final CommandRegistry commandRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* construct creates CommandRegistry for this bot.
|
||||||
|
* Use ICommandRegistry's methods on this bot to register commands
|
||||||
|
*/
|
||||||
|
public TelegramLongPollingCommandBot() {
|
||||||
|
this.commandRegistry = new CommandRegistry(getBotToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void onUpdateReceived(Update update) {
|
||||||
|
if (update.hasMessage()) {
|
||||||
|
Message message = update.getMessage();
|
||||||
|
if (message.isCommand()) {
|
||||||
|
if (!commandRegistry.executeCommand(this, message)) {
|
||||||
|
SendMessage sendMessage = new SendMessage();
|
||||||
|
sendMessage.setChatId(message.getChatId().toString());
|
||||||
|
sendMessage.setText("The command you provided is not registered for this bot");
|
||||||
|
try {
|
||||||
|
sendMessage(sendMessage);
|
||||||
|
} catch (TelegramApiException e) {
|
||||||
|
BotLogger.error("Cannot send message", LOGTAG, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
processNonCommandUpdate(update);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final boolean register(BotCommand botCommand) {
|
||||||
|
return commandRegistry.register(botCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Map<BotCommand, Boolean> registerAll(BotCommand... botCommands) {
|
||||||
|
return commandRegistry.registerAll(botCommands);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final boolean deregister(BotCommand botCommand) {
|
||||||
|
return commandRegistry.deregister(botCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Map<BotCommand, Boolean> deregisterAll(BotCommand... botCommands) {
|
||||||
|
return commandRegistry.deregisterAll(botCommands);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Collection<BotCommand> getRegisteredCommands() {
|
||||||
|
return commandRegistry.getRegisteredCommands();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process all updates, that are not commands.
|
||||||
|
* Attention: commands, that have valid syntax but are not registered on this bot,
|
||||||
|
* won't be forwarded to this method!
|
||||||
|
*
|
||||||
|
* @param update the update
|
||||||
|
*/
|
||||||
|
public abstract void processNonCommandUpdate(Update update);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user