### Complete ReplyFlow Bot Example Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/State-Machines A full example of an AbilityBot implementing a direction-based ReplyFlow. This demonstrates how to integrate ReplyFlows within your bot's structure. ```java public class ReplyFlowBot extends AbilityBot { public ReplyFlowBot(String botToken, String botUsername) { super(botToken, botUsername); } @Override public int creatorId() { return ; } public ReplyFlow directionFlow() { Reply saidLeft = Reply.of(upd -> silent.send("Sir, I have gone left.", getChatId(upd)), hasMessageWith("go left or else")); ReplyFlow leftflow = ReplyFlow.builder(db) .action(upd -> silent.send("I don't know how to go left.", getChatId(upd))) .onlyIf(hasMessageWith("left")) .next(saidLeft).build(); Reply saidRight = Reply.of(upd -> silent.send("Sir, I have gone right.", getChatId(upd)), hasMessageWith("right")); return ReplyFlow.builder(db) .action(upd -> silent.send("Command me to go left or right!", getChatId(upd))) .onlyIf(hasMessageWith("wake up")) .next(leftflow) .next(saidRight) .build(); } @NotNull private Predicate hasMessageWith(String msg) { return upd -> upd.getMessage().getText().equalsIgnoreCase(msg); } } ``` -------------------------------- ### Full Test Setup for Telegram Bot Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Bot-Testing Provides the complete setup for testing a Telegram bot, including necessary imports, mock sender initialization, and bot registration before running tests. ```java import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import org.telegram.abilitybots.api.db.DBContext; import org.telegram.abilitybots.api.db.MapDBContext; import org.telegram.abilitybots.api.objects.MessageContext; import org.telegram.abilitybots.api.sender.SilentSender; import org.telegram.telegrambots.meta.api.objects.Update; import org.telegram.telegrambots.meta.api.objects.User; import static org.mockito.Mockito.*; public class ExampleBotTest { public static final int USER_ID = 1337; public static final long CHAT_ID = 1337L; // Your bot handle here private ExampleBot bot; // Your sender here. Also you can create MessageSender private SilentSender silent; @Before public void setUp() { // Create your bot bot = new ExampleBot(); // Call onRegister() to initialize abilities etc. bot.onRegister(); // Create a new sender as a mock silent = mock(SilentSender.class); // Set your bot silent sender to the mocked sender // THIS is the line that prevents your bot from communicating with Telegram servers when it's running its own abilities // All method calls will go through the mocked interface -> which would do nothing except logging the fact that you've called this function with the specific arguments // Create setter in your bot bot.setSilentSender(silent); } @Test public void canSayHelloWorld() { Update upd = new Update(); // Create a new User - User is a class similar to Telegram User User user = new User(USER_ID, "Abbas", false, "Abou Daya", "addo37", null); // This is the context that you're used to, it is the necessary conumer item for the ability MessageContext context = MessageContext.newContext(upd, user, CHAT_ID); // We consume a context in the lamda declaration, so we pass the context to the action logic bot.saysHelloWorld().action().accept(context); // We verify that the silent sender was called only ONCE and sent Hello World to CHAT_ID // The silent sender here is a mock! Mockito.verify(silent, times(1)).send("Hello World!", CHAT_ID); } } ``` -------------------------------- ### Set up Offline DB and ExampleBot in Test Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Bot-Testing In your test setup, create an offline instance of DBContext using MapDBContext.offlineInstance and pass it to the ExampleBot constructor. The offline instance will be deleted at JVM shutdown. ```java db = MapDBContext.offlineInstance("test"); bot = new ExampleBot(db); bot.onRegister(); ``` -------------------------------- ### Defining a Simple 'Hello World' Ability Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Simple-Example Create a new ability by using the Ability builder. This example defines a 'hello' command that responds with 'Hello world!'. Ensure you have imported ALL and PUBLIC constants. ```java public Ability sayHelloWorld() { return Ability .builder() .name("hello") .info("says hello world!") .locality(ALL) .privacy(PUBLIC) .action(ctx -> silent.send("Hello world!", ctx.chatId())) .build(); } ``` -------------------------------- ### Handle Incoming Updates and Echo Messages Source: https://github.com/rubenlagus/telegrambots/wiki/Getting-Started Implement the `onUpdateReceived` method to process incoming messages. This example checks for text messages and echoes them back to the sender. ```java @Override public void onUpdateReceived(Update update) { // We check if the update has a message and the message has text if (update.hasMessage() && update.getMessage().hasText()) { SendMessage message = new SendMessage(); // Create a SendMessage object with mandatory fields message.setChatId(update.getMessage().getChatId().toString()); message.setText(update.getMessage().getText()); try { execute(message); // Call method to send the message } catch (TelegramApiException e) { e.printStackTrace(); } } } ``` -------------------------------- ### Customize Command Prefix Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Advanced Change the prefix used for bot commands by overriding the getCommandPrefix method. This example sets the prefix to '!'. ```java @Override protected String getCommandPrefix() { return "!"; } ``` -------------------------------- ### Customize Command Regex Split Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Advanced Modify how command tokens are split by overriding getCommandRegexSplit. This example splits on whitespace and digits. ```java @Override protected String getCommandRegexSplit() { return "\\s\\d"; } ``` -------------------------------- ### Get File Path for Photo Source: https://github.com/rubenlagus/telegrambots/wiki/FAQ Retrieves the file_path for a given PhotoSize. If the file_path is not directly available, it uses the file_id to fetch it. ```java public String getFilePath(PhotoSize photo) { Objects.requireNonNull(photo); if (photo.hasFilePath()) { // If the file_path is already present, we are done! return photo.getFilePath(); } else { // If not, let find it // We create a GetFile method and set the file_id from the photo GetFile getFileMethod = new GetFile(); getFileMethod.setFileId(photo.getFileId()); try { // We execute the method using AbsSender::execute method. File file = execute(getFileMethod); // We now have the file_path return file.getFilePath(); } catch (TelegramApiException e) { e.printStackTrace(); } } return null; // Just in case } ``` -------------------------------- ### Restrict Updates with Global Flags Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Advanced Override the checkGlobalFlags method to filter the types of updates your bot processes. This example restricts processing to photos only. ```java @Override public boolean checkGlobalFlags(Update update) { return Flag.PHOTO.test(update); } ``` -------------------------------- ### Execute Method and Get Message Object Source: https://github.com/rubenlagus/telegrambots/wiki/understanding-the-library/Understanding-The-Library Use the execute() method to send a request and retrieve the resulting Message object. This pattern applies to various methods that return a value. ```java Message thePollMessage = ourBot.execute(ourPoll); ``` -------------------------------- ### Instantiate ExampleBot with DBContext Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Bot-Testing When creating an ExampleBot, you can supply a DBContext argument to the constructor. This allows for the use of an offline database during testing. ```java public ExampleBot(DBContext db) { super(BOT_TOKEN, BOT_USERNAME, db); } ``` -------------------------------- ### Get PhotoSize from Update Source: https://github.com/rubenlagus/telegrambots/wiki/FAQ Extracts the largest PhotoSize object from an incoming message update. Returns null if no photo is present. ```java public PhotoSize getPhoto(Update update) { // Check that the update contains a message and the message has a photo if (update.hasMessage() && update.getMessage().hasPhoto()) { // When receiving a photo, you usually get different sizes of it List photos = update.getMessage().getPhoto(); // We fetch the bigger photo return photos.stream() .max(Comparator.comparing(PhotoSize::getFileSize)).orElse(null); } // Return null if not found return null; } ``` -------------------------------- ### Create a /hello command with AbilityBot Source: https://github.com/rubenlagus/telegrambots/blob/master/telegrambots-abilities/README.md Defines a '/hello' command using the AbilityBot abstraction. Use this to create commands with specific names, info, input requirements, locality, privacy, and actions. ```java public Ability sayHelloWorld() { return Ability .builder() .name("hello") .info("says hello world!") .input(0) .locality(USER) .privacy(ADMIN) .action(ctx -> sender.send("Hello world!", ctx.chatId())) .post(ctx -> sender.send("Bye world!", ctx.chatId())) .build(); } ``` -------------------------------- ### Create a /hello Command Ability Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Hello-Ability Defines a simple '/hello' command using the Ability builder. Specify the command name, info, input requirements, locality (where it's available), privacy (who can use it), action logic, and post-action logic. ```java public Ability sayHelloWorld() { return Ability .builder() .name("hello") .info("says hello world!") .input(0) .locality(USER) .privacy(ADMIN) .action(ctx -> silent.send("Hello world!", ctx.chatId())) .post(ctx -> silent.send("Bye world!", ctx.chatId())) .build(); } ``` -------------------------------- ### Running the AbilityBot Application Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Simple-Example This main method demonstrates how to initialize and register your AbilityBot with the TelegramBotsApi. It uses DefaultBotSession for managing the bot's lifecycle. ```java public class Application { public static void main(String[] args) { try { // Create the TelegramBotsApi object to register your bots TelegramBotsApi botsApi = new TelegramBotsApi(DefaultBotSession.class); // Register your newly created AbilityBot botsApi.registerBot(new HelloBot()); } catch (TelegramApiException e) { e.printStackTrace(); } } } ``` -------------------------------- ### Run Jar with Command Line Argument Source: https://github.com/rubenlagus/telegrambots/wiki/Handling-Bot-Tokens Execute a Java JAR file and pass the bot token as the first command-line argument. ```bash java -jar myBot.jar [BOT_TOKEN] ``` -------------------------------- ### Basic Bot Method for Testing Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Bot-Testing This Java method demonstrates sending a 'Hello!' message. Testing this directly is difficult because `execute` is a final method, making it hard to verify if it was called without actually sending a message. ```java public void sayHello() { SendMessage snd = new SendMessage(); snd.setText("Hello!"); snd.setChatId(123); try { // We want to test that we actually sent out this message with the contents "Hello!" execute(snd); } catch (TelegramApiException e) {} } ``` -------------------------------- ### Use CustomToggle to disable or rename abilities Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Ability-Toggle CustomToggle allows disabling specific abilities or renaming them. For example, 'ban' is turned off, and 'promote' is renamed to 'upgrade'. Pass an instance of CustomToggle to the super constructor. ```java import org.telegram.abilitybots.api.toggle.CustomToggle; public class YourAwesomeBot extends AbilityBot { private static final CustomToggle toggle = new CustomToggle() .turnOff("ban") .toggle("promote", "upgrade"); public YourAwesomeBot(String token, String username) { super(token, username, toggle); } // Override ceatorId() } ``` -------------------------------- ### Execute GetMe Method with Telegram Bots Library Source: https://github.com/rubenlagus/telegrambots/wiki/understanding-the-library/Understanding-The-Library Initializes a bot and executes the GetMe method using the library to retrieve bot information. This demonstrates the library's object-oriented approach to API interactions. ```java AbsSender ourBot = getOurBot(); GetMe getMe = new GetMe(); User bot = ourBot.execute(getMe); ``` -------------------------------- ### Implement /hello command with basic Telegram Bot API Source: https://github.com/rubenlagus/telegrambots/blob/master/telegrambots-abilities/README.md This snippet shows how to implement a '/hello' command using the basic Telegram Bot Java API. It requires manual handling of updates, message checks, user permissions, and message sending, including error handling for API exceptions. ```java @Override public void onUpdateReceived(Update update) { // Global checks... // Switch, if, logic to route to hello world method // Execute method } public void sayHelloWorld(Update update) { if (!update.hasMessage() || !update.getMessage().isUserMessage() || !update.getMessage().hasText() || update.getMessage.getText().isEmpty()) return; User maybeAdmin = update.getMessage().getFrom(); /* Query DB for if the user is an admin, can be SQL, Reddis, Ignite, etc... If user is not an admin, then return here. */ SendMessage snd = new SendMessage(); snd.setChatId(update.getMessage().getChatId()); snd.setText("Hello world!"); try { sendMessage(snd); } catch (TelegramApiException e) { BotLogger.error("Could not send message", TAG, e); } } ``` -------------------------------- ### Define MyBot with DefaultBotOptions Source: https://github.com/rubenlagus/telegrambots/wiki/Using-Http-Proxy Override the constructor of your bot class to accept DefaultBotOptions. This is necessary for setting up proxy configurations. ```java public class MyBot extends AbilityBot { protected MyBot(String botToken, String botUsername, DefaultBotOptions botOptions) { super(botToken, botUsername, botOptions); } public int creatorId() { return 0; } public Ability pingPong() { return Ability .builder() .name("ping") .info("ping pong") .locality(ALL) .privacy(PUBLIC) .action(ctx -> silent.send("pong", ctx.chatId())) .build(); } } ``` -------------------------------- ### Initialize TelegramBotsApi in v5.0.0 Source: https://github.com/rubenlagus/telegrambots/wiki/How-To-Update In version 5.0.0, ApiContextInitializer.init() is removed. Use the new TelegramBotsApi constructor. For webhook bots, provide a custom DefaultWebhook instance. ```java TelegramBotsApi telegramBotsApi = new TelegramBotsApi(DefaultBotSession.class); ``` ```java TelegramBotsApi telegramBotsApi = new TelegramBotsApi(DefaultBotSession.class, defaultWebhookInstance); ``` -------------------------------- ### Build a Simple ReplyFlow Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/State-Machines Construct a ReplyFlow that prompts the user for input and then chains to other replies based on user responses. This flow is triggered by a specific message. ```java ReplyFlow.builder(db) // Just like replies, a ReplyFlow can take an action, here we want to send a // statement to prompt the user for directions! .action(upd -> silent.send("Command me to go left or right!", getChatId(upd))) // We should only trigger this flow when the user says "wake up" .onlyIf(hasMessageWith("wake up")) // The next method takes in an object of type Reply. // Here we chain our replies together .next(saidLeft) // We chain one more reply, which is when the user commands your bot to go right .next(saidRight) // Finally, we build our ReplyFlow .build(); ``` -------------------------------- ### Instantiate TelegramBotsApi Source: https://github.com/rubenlagus/telegrambots/wiki/Getting-Started Create an instance of `TelegramBotsApi` to manage your bots. Specify `DefaultBotSession.class` for standard long polling behavior. ```java TelegramBotsApi botsApi = new TelegramBotsApi(DefaultBotSession.class); ``` -------------------------------- ### Initialize API Context Source: https://github.com/rubenlagus/telegrambots/wiki/How-To-Update Add this line at the beginning of your program before creating your TelegramBotsApi or Bot instance. This is required for versions 2.4.3 and later. ```java ApiContextInitializer.init(); ``` -------------------------------- ### Send 'Hello World' Message to User Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Hello-Ability This method processes user messages, checks if the sender is an admin (requires external DB check), and sends a 'Hello world!' reply. It includes error handling for message execution. ```java public void sayHelloWorld(Update update) { if (!update.hasMessage() || !update.getMessage().isUserMessage() || !update.getMessage().hasText() || update.getMessage.getText().isEmpty()) return; User maybeAdmin = update.getMessage().getFrom(); /* Query DB for if the user is an admin, can be SQL, Reddis, Ignite, etc... If user is not an admin, then return here. */ SendMessage snd = new SendMessage(); snd.setChatId(update.getMessage().getChatId()); snd.setText("Hello world!"); try { execute(snd); } catch (TelegramApiException e) { BotLogger.error("Could not send message", TAG, e); } } ``` -------------------------------- ### AbilityBot Constructor with Static Constants Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Simple-Example Alternatively, use static constants for the bot token and username if they are fixed. ```java public static String BOT_TOKEN = "..."; public static String BOT_USERNAME = "..."; public HelloBot() { super(BOT_TOKEN, BOT_USERNAME); } ``` -------------------------------- ### Instantiate and Send a Poll Source: https://github.com/rubenlagus/telegrambots/wiki/understanding-the-library/Understanding-The-Library Demonstrates how to create a SendPoll object with required parameters and execute it using an AbsSender instance. Assumes chatMessage is available and getOurBot() provides the sender. ```java AbsSender ourBot = getOurBot(); List options = new List<>(); options.add("Yes"); options.add("No"); // Let's just assume we get the chatMessage as a parameter. For example from the message received, or from a database SendPoll ourPoll = new SendPoll(someChatId, "Some Question", options); ourBot.execute(ourPoll); ``` -------------------------------- ### AbilityBot Constructor with Token and Username Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Simple-Example Implement the constructor to pass the bot token and username to the superclass. These are required for bot initialization. ```java public HelloBot(String token, String username) { super(token, username); } ``` -------------------------------- ### Handle Incoming Telegram Updates Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Hello-Ability This method is the entry point for all updates received by the bot. It should contain logic to route updates to appropriate handlers. ```java @Override public void onUpdateReceived(Update update) { // Global checks... // Switch, if, logic to route to hello world method // Execute method } ``` -------------------------------- ### Basic AbilityBot Declaration Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Simple-Example Extend the AbilityBot class to create your bot. This is the fundamental step for using the abilities module. ```java import org.telegram.abilitybots.api.bot.AbilityBot; public class HelloBot extends AbilityBot { ... } ``` -------------------------------- ### Execute Custom Logic on Bot Registration Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Advanced Override the onRegister method to execute custom initialization logic when the bot is registered. Ensure to call super.onRegister() if needed. ```java @Override public void onRegister() { super.onRegister(); // Execute custom initialize logic here } ``` -------------------------------- ### Set Files Using InputFile Source: https://github.com/rubenlagus/telegrambots/wiki/How-To-Update Use InputFile to set files for uploading, either with a File object or a Stream. This replaces older, specific setters. ```java // With a file SendDocument .builder() .chatId("123456") .document(new InputFile(new File("Filename.pdf"))) .build() // With a Stream SendDocument .builder() .chatId("123456") .document(new InputFile("FileName", new FileInputStream("Filename.pdf"))) .build() ``` -------------------------------- ### Set Environment Variable on Windows Source: https://github.com/rubenlagus/telegrambots/wiki/Handling-Bot-Tokens Use the SETX command in CMD to set a persistent environment variable on Windows. Replace VARIABLE_NAME and YOUR_BOT_TOKEN with your actual variable name and bot token. ```batchfile SETX [VARIABLE_NAME] [YOUR_BOT_TOKEN] ``` -------------------------------- ### Create Basic Replies Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/State-Machines Define individual replies that respond to specific user messages. These are the building blocks for ReplyFlows. ```java Reply saidLeft = Reply.of(upd -> silent.send("Sir, I have gone left.", getChatId(upd)), hasMessageWith("left")); Reply saidRight = Reply.of(upd -> silent.send("Sir, I have gone right.", getChatId(upd)), hasMessageWith("right")); ``` -------------------------------- ### Logging Framework Change Source: https://github.com/rubenlagus/telegrambots/wiki/How-To-Update The logging framework has been replaced by slf4j. You need to manage your own slf4j implementation. -------------------------------- ### Set up SilentSender in Test Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Bot-Testing To test abilities that use the silent message sender, create a SilentSender instance with a mocked MessageSender and set it in your bot. Assertions should be made on the mocked sender object. ```java sender = mock(MessageSender.class); SilentSender silent = new SilentSender(sender); // Create setter in your bot bot.setSilentSender(silent); ``` -------------------------------- ### Send InlineKeyboardMarkup Source: https://github.com/rubenlagus/telegrambots/wiki/FAQ Implement this method to send a message with an InlineKeyboardMarkup. Each button in an InlineKeyboardMarkup must have a URL or a callback data. ```java public void sendInlineKeyboard(String chatId) { SendMessage message = new SendMessage(); message.setChatId(chatId); message.setText("Inline model below."); // Create InlineKeyboardMarkup object InlineKeyboardMarkup inlineKeyboardMarkup = new InlineKeyboardMarkup(); // Create the keyboard (list of InlineKeyboardButton list) List> keyboard = new ArrayList<>(); // Create a list for buttons List Buttons = new ArrayList(); // Initialize each button, the text must be written InlineKeyboardButton youtube= new InlineKeyboardButton("youtube"); // Also must use exactly one of the optional fields,it can edit by set method youtube.setUrl("https://www.youtube.com"); // Add button to the list Buttons.add(youtube); // Initialize each button, the text must be written InlineKeyboardButton github= new InlineKeyboardButton("github"); // Also must use exactly one of the optional fields,it can edit by set method github.setUrl("https://github.com"); // Add button to the list Buttons.add(github); keyboard.add(Buttons); inlineKeyboardMarkup.setKeyboard(keyboard); // Add it to the message message.setReplyMarkup(inlineKeyboardMarkup); try { // Send the message execute(message); } catch (TelegramApiException e) { e.printStackTrace(); } } ``` -------------------------------- ### Create a More Complex ReplyFlow with State Transition Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/State-Machines Define a ReplyFlow that includes a state transition, allowing for more intricate conversational logic. This flow handles a specific user input and then proceeds to another reply. ```java ReplyFlow leftflow = ReplyFlow.builder(db) .action(upd -> silent.send("I don't know how to go left.", getChatId(upd))) .onlyIf(hasMessageWith("left")) .next(saidLeft) .build(); ``` -------------------------------- ### Define Custom Ability Extensions Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Ability-Extensions Implement the AbilityExtension interface to create modular ability groups. Each extension should provide methods that return Ability objects. ```java public class MrGoodGuy implements AbilityExtension { private AbilityBot extensionUser; public MrGoodGuy(AbilityBot extensionUser) { this.extensionUser = extensionUser; } public Ability nice() { return Ability.builder() .name("nice") .privacy(PUBLIC) .locality(ALL) .action(ctx -> extensionUser.silent().send("You're awesome!", ctx.chatId())) ); } } ``` ```java public class MrBadGuy implements AbilityExtension { private AbilityBot extensionUser; public MrBadGuy(AbilityBot extensionUser) { this.extensionUser = extensionUser; } public Ability notnice() { return Ability.builder() .name("notnice") .privacy(PUBLIC) .locality(ALL) .action(ctx -> extensionUser.silent().send("You're horrible!", ctx.chatId())) ); } } ``` -------------------------------- ### Download Photo by File Path Source: https://github.com/rubenlagus/telegrambots/wiki/FAQ Downloads a file using its file_path. Requires the file_path to be previously obtained. ```java public java.io.File downloadPhotoByFilePath(String filePath) { try { // Download the file calling AbsSender::downloadFile method return downloadFile(filePath); } catch (TelegramApiException e) { e.printStackTrace(); } return null; } ``` -------------------------------- ### Access Bot Token from Command Line Arguments Source: https://github.com/rubenlagus/telegrambots/wiki/Handling-Bot-Tokens Read the bot token from the first command-line argument passed to the application's main method. This method is not recommended for security reasons. ```java public static void main(String[] args) { String botToken = args[0]; } ``` -------------------------------- ### Register Bot with TelegramBotsApi Source: https://github.com/rubenlagus/telegrambots/wiki/Getting-Started Register an instance of your custom bot class with the `TelegramBotsApi`. This makes your bot active and ready to receive updates. Ensure this is done within a try-catch block to handle potential `TelegramApiException`. ```java try { TelegramBotsApi botsApi = new TelegramBotsApi(DefaultBotSession.class); botsApi.registerBot(new MyAmazingBot()); } catch (TelegramApiException e) { e.printStackTrace(); } ``` -------------------------------- ### Configure HTTP Proxy With Authentication Source: https://github.com/rubenlagus/telegrambots/wiki/Using-Http-Proxy Configure your Telegram bot to use a proxy that requires authentication. This involves setting up a Java Authenticator with proxy credentials. ```java public class Main { private static String BOT_NAME = "My test bot"; private static String BOT_TOKEN = "..." /* your bot's token here */; private static String PROXY_HOST = "..." /* proxy host */; private static Integer PROXY_PORT = 3128 /* proxy port */; private static String PROXY_USER = "..." /* proxy user */; private static String PROXY_PASSWORD = "..." /* proxy password */; public static void main(String[] args) { try { // Create the Authenticator that will return auth's parameters for proxy authentication Authenticator.setDefault(new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(PROXY_USER, PROXY_PASSWORD.toCharArray()); } }); // Create the TelegramBotsApi object to register your bots TelegramBotsApi botsApi = new TelegramBotsApi(DefaultBotSession.class); // Set up Http proxy DefaultBotOptions botOptions = new DefaultBotOptions(); botOptions.setProxyHost(PROXY_HOST); botOptions.setProxyPort(PROXY_PORT); // Select proxy type: [HTTP|SOCKS4|SOCKS5] (default: NO_PROXY) botOptions.setProxyType(DefaultBotOptions.ProxyType.SOCKS5); // Register your newly created AbilityBot MyBot bot = new MyBot(BOT_TOKEN, BOT_NAME, botOptions); botsApi.registerBot(bot); } catch (TelegramApiException e) { e.printStackTrace(); } } } ``` -------------------------------- ### Define a Telegram Bot Ability Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Bot-Testing Defines an ability that sends a 'Hello World!' message. It includes error handling for Telegram API exceptions. ```java public Ability saysHelloWorld() { return Ability.builder() .name("hello") .info("Says hello world!") .privacy(PUBLIC) .locality(ALL) .action(ctx -> { try{ sender.execute(new SendMessage().setChatId(ctx.getChatId()).setText("Hello World!")); } catch (TelgramApiException e){} }) .build(); } ``` -------------------------------- ### Send Sticker by File ID or URL Source: https://github.com/rubenlagus/telegrambots/wiki/FAQ This method sends a sticker to a chat. It accepts either a sticker's file ID (obtained from @idstickerbot) or a direct URL to a .webp sticker. ```java // Sticker_file_id is received from @idstickerbot bot private void StickerSender(Update update, String Sticker_file_id) { //the ChatId that we received form Update class String ChatId = update.getMessage().getChatId().toString(); // Create an InputFile containing Sticker's file_id or URL InputFile StickerFile = new InputFile(Sticker_file_id); // Create a SendSticker object using the ChatId and StickerFile SendSticker TheSticker = new SendSticker(ChatId, StickerFile); // Will reply the sticker to the message sent //TheSticker.setReplyToMessageId(update.getMessage().getMessageId()); try { // Execute the method execute(TheSticker); } catch (TelegramApiException e) { e.printStackTrace(); } } ``` -------------------------------- ### Allow Continuous Text with Commands Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Advanced Enable processing of tokens attached to commands by overriding allowContinuousText. This allows commands like '/do1' to trigger the 'do' ability. ```java @Override protected boolean allowContinuousText() { return true; } ``` -------------------------------- ### Enabling Stats for Abilities Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Simple-Example To track the usage count of your abilities, add .setStatsEnabled(true) to the ability builder. This is required for the /stats command to function. ```java .setStatsEnabled(true) ``` -------------------------------- ### Access Bot Token in Java Source: https://github.com/rubenlagus/telegrambots/wiki/Handling-Bot-Tokens Retrieve the bot token from environment variables in a Java application using System.getenv(). Ensure the environment variable 'VARIABLE_NAME' is set. ```java String BOT_TOKEN = System.getenv("VARIABLE_NAME"); ``` -------------------------------- ### Send Custom ReplyKeyboardMarkup Source: https://github.com/rubenlagus/telegrambots/wiki/FAQ Use this method to send a message with a custom ReplyKeyboardMarkup. Ensure the ReplyKeyboardMarkup is properly configured with KeyboardRows and buttons. ```java public void sendCustomKeyboard(String chatId) { SendMessage message = new SendMessage(); message.setChatId(chatId); message.setText("Custom message text"); // Create ReplyKeyboardMarkup object ReplyKeyboardMarkup keyboardMarkup = new ReplyKeyboardMarkup(); // Create the keyboard (list of keyboard rows) List keyboard = new ArrayList<>(); // Create a keyboard row KeyboardRow row = new KeyboardRow(); // Set each button, you can also use KeyboardButton objects if you need something else than text row.add("Row 1 Button 1"); row.add("Row 1 Button 2"); row.add("Row 1 Button 3"); // Add the first row to the keyboard keyboard.add(row); // Create another keyboard row row = new KeyboardRow(); // Set each button for the second line row.add("Row 2 Button 1"); row.add("Row 2 Button 2"); row.add("Row 2 Button 3"); // Add the second row to the keyboard keyboard.add(row); // Set the keyboard to the markup keyboardMarkup.setKeyboard(keyboard); // Add it to the message message.setReplyMarkup(keyboardMarkup); try { // Send the message execute(message); } catch (TelegramApiException e) { e.printStackTrace(); } } ``` -------------------------------- ### Spring Webhook Bot Implementation Source: https://github.com/rubenlagus/telegrambots/wiki/How-To-Update For Spring integration with webhook bots, extend SpringWebhookBot and provide the SetWebhook method in the constructor. Define beans for SetWebhook and the bot itself. ```java // Extend correct class public class TestSpringWebhookBot extends SpringWebhookBot { public TestSpringWebhookBot(SetWebhook setWebhook) { super(setWebhook); } public TestSpringWebhookBot(DefaultBotOptions options, SetWebhook setWebhook) { super(options, setWebhook); } @Override public String getBotUsername() { return null; } @Override public String getBotToken() { return null; } @Override public BotApiMethod onWebhookUpdateReceived(Update update) { return null; } @Override public String getBotPath() { return null; } } // Create your SetWebhook method @Bean public SetWebhook setWebhookInstance() { return SetWebhook.builder()....build(); } // Create it as @Bean public TestSpringWebhookBot testSpringWebhookBot(SetWebhook setWebhookInstance) { return new TestSpringWebhookBot(setWebhookInstance); } ``` -------------------------------- ### Configure HTTP Proxy Without Authentication Source: https://github.com/rubenlagus/telegrambots/wiki/Using-Http-Proxy Set up a Telegram bot to use an HTTP or SOCKS proxy without requiring authentication. Ensure the proxy host, port, and type are correctly specified. ```java public class Main { private static String BOT_NAME = "My test bot"; private static String BOT_TOKEN = "..." /* your bot's token here */; private static String PROXY_HOST = "..." /* proxy host */; private static Integer PROXY_PORT = 3128 /* proxy port */; public static void main(String[] args) { try { // Create the TelegramBotsApi object to register your bots TelegramBotsApi botsApi = new TelegramBotsApi(DefaultBotSessioin.class); // Set up Http proxy DefaultBotOptions botOptions = new DefaultBotOptions(); botOptions.setProxyHost(PROXY_HOST); botOptions.setProxyPort(PROXY_PORT); // Select proxy type: [HTTP|SOCKS4|SOCKS5] (default: NO_PROXY) botOptions.setProxyType(DefaultBotOptions.ProxyType.SOCKS5); // Register your newly created AbilityBot MyBot bot = new MyBot(BOT_TOKEN, BOT_NAME, botOptions); botsApi.registerBot(bot); } catch (TelegramApiException e) { e.printStackTrace(); } } } ``` -------------------------------- ### Use BareboneToggle to disable all default abilities Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Ability-Toggle Use BareboneToggle to turn off all default abilities like ban, unban, demote, promote, etc. Pass an instance of BareboneToggle to the super constructor. ```java import org.telegram.abilitybots.api.toggle.BareboneToggle; public class YourAwesomeBot extends AbilityBot { private static final BareboneToggle toggle = new BareboneToggle(); public YourAwesomeBot(String token, String username) { super(token, username, toggle); } // Override ceatorId() } ``` -------------------------------- ### Helper Method for Message Matching Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/State-Machines A utility method to create a predicate that checks if a message's text matches a given string, ignoring case. ```java private Predicate hasMessageWith(String msg) { return upd -> upd.getMessage().getText().equalsIgnoreCase(msg); } ``` -------------------------------- ### Add Telegram Bots Extensions Dependency (Gradle) Source: https://github.com/rubenlagus/telegrambots/blob/master/telegrambots-extensions/README.md Add this line to your Gradle build file to include the telegrambots-extensions library. ```gradle implementation 'org.telegram:telegrambots-extensions:9.6.0' ``` -------------------------------- ### Declare Standalone Reply to Images Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Using-Replies Creates a reply that sends 'Yuck' when an image is received. Requires the `Reply.of` method and `Flag.PHOTO` condition. ```java /** * A reply that says "yuck" to all images sent to the bot. */ public Reply sayYuckOnImage() { // getChatId is a public utility function in rg.telegram.abilitybots.api.util.AbilityUtils Consumer action = upd -> silent.send("Yuck", getChatId(upd)); return Reply.of(action, Flag.PHOTO); } ``` -------------------------------- ### Implement Default Ability for Non-Command Messages Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Advanced Define a default ability that processes messages when no specific command is given. This ability requires a photo to activate and is triggered by default if no /command is provided. ```java /** * This ability has an extra "flag". It needs a photo to activate! This feature is activated by default if there is no /command given. */ public Ability sayNiceToPhoto() { return Ability.builder() .name(DEFAULT) // DEFAULT ability is executed if user did not specify a command -> Bot needs to have access to messages (check FatherBot) .flag(PHOTO) .privacy(PUBLIC) .locality(ALL) .input(0) .action(ctx -> silent.send("Daaaaang, what a nice photo!", ctx.chatId())) .build(); } ``` -------------------------------- ### Basic TelegramLongPollingBot Structure Source: https://github.com/rubenlagus/telegrambots/wiki/Getting-Started Define the core structure of your bot by extending `TelegramLongPollingBot` and implementing essential methods. This serves as the foundation for your bot's logic. ```java public class MyAmazingBot extends TelegramLongPollingBot { @Override public void onUpdateReceived(Update update) { // TODO } @Override public String getBotUsername() { // TODO return null; } @Override public String getBotToken() { // TODO return null; } } ``` -------------------------------- ### Send Photo from URL Source: https://github.com/rubenlagus/telegrambots/wiki/FAQ Use this method to send a photo to a chat using its URL. Ensure the URL points to a valid image file. ```java public void sendImageFromUrl(String url, String chatId) { // Create send method SendPhoto sendPhotoRequest = new SendPhoto(); // Set destination chat id sendPhotoRequest.setChatId(chatId); // Set the photo url as a simple photo sendPhotoRequest.setPhoto(new InputFile(url)); try { // Execute the method execute(sendPhotoRequest); } catch (TelegramApiException e) { e.printStackTrace(); } } ``` -------------------------------- ### Add Telegram Bots Extensions Dependency (Maven) Source: https://github.com/rubenlagus/telegrambots/blob/master/telegrambots-extensions/README.md Include this dependency in your Maven project to use the telegrambots-extensions library. ```xml org.telegram telegrambots-extensions 9.6.0 ``` -------------------------------- ### Add Telegram Bots Dependency with Maven Source: https://github.com/rubenlagus/telegrambots/wiki/Getting-Started Use this XML snippet in your Maven project's pom.xml to include the Telegram Bots library. ```xml org.telegram telegrambots 6.9.7.1 ``` -------------------------------- ### Add Ability Extensions in Constructor Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Ability-Extensions Alternatively, add Ability Extensions directly in the constructor of your AbilityBot using addExtension() or addExtensions(). ```java public class YourAwesomeBot implements AbilityBot { public YourAwesomeBot() { super(/* pass required args ... */); addExtensions(new MrGoodGuy(this), new MrBadGuy(this)); } // Override creatorId } ``` -------------------------------- ### Register Ability Extensions in AbilityBot Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Ability-Extensions Register custom Ability Extensions by returning them from methods within your AbilityBot implementation. The bot will discover these extensions. ```java public class YourAwesomeBot implements AbilityBot { // Constructor for your bot public AbilityExtension goodGuy() { return new MrGoodGuy(this); } public AbilityExtension badGuy() { return new MrBadGuy(this); } // Override creatorId } ``` -------------------------------- ### Add Telegram Bots Dependency with Gradle Source: https://github.com/rubenlagus/telegrambots/wiki/Getting-Started Add this line to your Gradle project's build.gradle file to incorporate the Telegram Bots library. ```gradle implementation 'org.telegram:telegrambots:6.9.7.1' ``` -------------------------------- ### Implement getBotToken Method Source: https://github.com/rubenlagus/telegrambots/wiki/Getting-Started Return your bot's secret token in the `getBotToken()` method. This token is essential for authenticating your bot with the Telegram API. ```java @Override public String getBotToken() { return "123456789:qwertyuioplkjhgfdsazxcvbnm"; } ``` -------------------------------- ### Spring Component Bot Implementation Source: https://github.com/rubenlagus/telegrambots/wiki/FAQ Implement your bot by extending `TelegramLongPollingBot` and annotating it with `@Component` for Spring to manage. ```java //Standard Spring component annotation @Component public class YourBotClassName extends TelegramLongPollingBot { //Bot body. } ``` -------------------------------- ### Register Webhook Bot with SetWebhook Source: https://github.com/rubenlagus/telegrambots/wiki/How-To-Update When registering a webhook bot, you must provide a SetWebhook method object to the TelegramBotsApi. ```java TelegramBotsApi telegramBotsApi = new TelegramBotsApi(DefaultBotSession.class, defaultWebhookInstance); telegramApi.registerBot(myWebhookBot, mySetWebhook); ``` -------------------------------- ### Send Chat Actions Source: https://github.com/rubenlagus/telegrambots/wiki/FAQ Sends a chat action to indicate the bot's current activity, such as typing or recording audio. Requires an Update object and a command text to determine the action. ```java if (update.hasMessage() && update.getMessage().hasText()) { String text = update.getMessage().getText(); SendChatAction sendChatAction = new SendChatAction(); sendChatAction.setChatId(update.getMessage().getChatId()); if (text.equals("/type")) { // -> "typing" sendChatAction.setAction(ActionType.TYPING); // -> "recording a voice message" } else if (text.equals("/record_audio")) { sendChatAction.setAction(ActionType.RECORDAUDIO); } else { // -> more actions in the Enum ActionType // For information: https://core.telegram.org/bots/api#sendchataction sendChatAction.setAction(ActionType.UPLOADDOCUMENT); } try { Boolean wasSuccessfull = execute(sendChatAction); } catch (TelegramApiException e) { // TODO Auto-generated catch block e.printStackTrace(); } } ``` -------------------------------- ### Spring Boot Main Application Class Source: https://github.com/rubenlagus/telegrambots/wiki/FAQ This is the main class for a Spring Boot application. It should be annotated with `@SpringBootApplication`. ```java @SpringBootApplication public class YourApplicationMainClass { public static void main(String[] args) { SpringApplication.run(YourApplicationMainClass.class, args); } } ``` -------------------------------- ### Declare Ability Reply with Custom Predicates Source: https://github.com/rubenlagus/telegrambots/wiki/abilities/Using-Replies Attaches a reply to an ability that responds to specific messages and replies to the bot. Includes custom predicates `isReplyToMessage` and `isReplyToBot`. ```java public Ability playWithMe() { String playMessage = "Play with me!"; return Ability.builder() .name("play") .info("Do you want to play with me?") .privacy(PUBLIC) .locality(ALL) .input(0) .action(ctx -> silent.forceReply(playMessage, ctx.chatId())) // The signature of a reply is -> (Consumer action, Predicate... conditions) // So, we first declare the action that takes an update (NOT A MESSAGECONTEXT) like the action above // The reason of that is that a reply can be so versatile depending on the message, context becomes an inefficient wrapping .reply((abilityBot,upd) -> { // Prints to console System.out.println("I'm in a reply!"); // Sends message silent.send("It's been nice playing with you!", upd.getMessage().getChatId()); }, // Now we start declaring conditions, MESSAGE is a member of the enum Flag class // That class contains out-of-the-box predicates for your replies! // MESSAGE means that the update must have a message // This is imported statically, Flag.MESSAGE MESSAGE, // REPLY means that the update must be a reply, Flag.REPLY REPLY, // A new predicate user-defined // The reply must be to the bot isReplyToBot(), // If we process similar logic in other abilities, then we have to make this reply specific to this message // The reply is to the playMessage isReplyToMessage(playMessage) ) // You can add more replies by calling .reply(...) .build(); } private Predicate isReplyToMessage(String message) { return upd -> { Message reply = upd.getMessage().getReplyToMessage(); return reply.hasText() && reply.getText().equalsIgnoreCase(message); }; } private Predicate isReplyToBot() { return upd -> upd.getMessage().getReplyToMessage().getFrom().getUserName().equalsIgnoreCase(getBotUsername()); } ```