diff --git a/TelegramBots.wiki/Changelog.md b/TelegramBots.wiki/Changelog.md
index 1358a72a..418a5d26 100644
--- a/TelegramBots.wiki/Changelog.md
+++ b/TelegramBots.wiki/Changelog.md
@@ -6,6 +6,7 @@
5. Locations now use Double instead of Float to avoid rounding.
6. When registering a Webhook Bot, a SetWebhook object must be provided.
7. When using Webhook with Spring, extends class SpringWebhookBot instead of WebhookBot
+8. New Async methods returning CompletableFutures.
### 4.9.2 ###
1. Bug fixing: #792, #801, #804, #810, #812, #813, #820 and #814
diff --git a/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/objects/passport/dataerror/PassportElementErrorTranslationFiles.java b/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/objects/passport/dataerror/PassportElementErrorTranslationFiles.java
index f2be141f..61212a33 100644
--- a/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/objects/passport/dataerror/PassportElementErrorTranslationFiles.java
+++ b/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/objects/passport/dataerror/PassportElementErrorTranslationFiles.java
@@ -66,14 +66,4 @@ public class PassportElementErrorTranslationFiles implements PassportElementErro
throw new TelegramApiValidationException("Type parameter can't be empty", this);
}
}
-
- @Override
- public String toString() {
- return "PassportElementErrorTranslationFiles{" +
- "source='" + source + '\'' +
- ", type='" + type + '\'' +
- ", fileHashes=" + fileHashes +
- ", message='" + message + '\'' +
- '}';
- }
}
diff --git a/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/bots/AbsSender.java b/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/bots/AbsSender.java
index 204bb1fa..ccf9e8ae 100644
--- a/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/bots/AbsSender.java
+++ b/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/bots/AbsSender.java
@@ -27,6 +27,7 @@ import org.telegram.telegrambots.meta.updateshandlers.SentCallback;
import java.io.Serializable;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
/**
* @author Ruben Bermudez
@@ -49,6 +50,13 @@ public abstract class AbsSender {
sendApiMethodAsync(method, callback);
}
+ public > CompletableFuture executeAsync(Method method) throws TelegramApiException {
+ if (method == null) {
+ throw new TelegramApiException("Parameter method can not be null");
+ }
+ return sendApiMethodAsync(method);
+ }
+
public > T execute(Method method) throws TelegramApiException {
if (method == null) {
throw new TelegramApiException("Parameter method can not be null");
@@ -70,6 +78,15 @@ public abstract class AbsSender {
// Send Requests Async
+
+ public final CompletableFuture getMeAsync() {
+ return sendApiMethodAsync(new GetMe());
+ }
+
+ public final CompletableFuture getWebhookInfoAsync() {
+ return sendApiMethodAsync(new GetWebhookInfo());
+ }
+
public final void getMeAsync(SentCallback sentCallback) throws TelegramApiException {
if (sentCallback == null) {
throw new TelegramApiException("Parameter sentCallback can not be null");
@@ -175,9 +192,94 @@ public abstract class AbsSender {
*/
public abstract Message execute(SendAnimation sendAnimation) throws TelegramApiException;
+
+ // Specific Send Requests Async
+
+ public abstract CompletableFuture executeAsync(SendDocument sendDocument);
+
+ public abstract CompletableFuture executeAsync(SendPhoto sendPhoto);
+
+ public abstract CompletableFuture executeAsync(SendVideo sendVideo);
+
+ public abstract CompletableFuture executeAsync(SendVideoNote sendVideoNote);
+
+ public abstract CompletableFuture executeAsync(SendSticker sendSticker);
+
+ /**
+ * Sends a file using Send Audio method (https://core.telegram.org/bots/api#sendaudio)
+ * @param sendAudio Information to send
+ * @return If success, the sent Message is returned
+ */
+ public abstract CompletableFuture executeAsync(SendAudio sendAudio);
+
+ /**
+ * Sends a voice note using Send Voice method (https://core.telegram.org/bots/api#sendvoice)
+ * For this to work, your audio must be in an .ogg file encoded with OPUS
+ * @param sendVoice Information to send
+ * @return If success, the sent Message is returned
+ */
+ public abstract CompletableFuture executeAsync(SendVoice sendVoice);
+
+ /**
+ * Send a media group (https://core.telegram.org/bots/api#sendMediaGroup)
+ * @return If success, list of generated messages
+ */
+ public abstract CompletableFuture> executeAsync(SendMediaGroup sendMediaGroup);
+
+ /**
+ * Set chat profile photo (https://core.telegram.org/bots/api#setChatPhoto)
+ * @param setChatPhoto Information to set the photo
+ * @return If success, true is returned
+ */
+ public abstract CompletableFuture executeAsync(SetChatPhoto setChatPhoto);
+
+ /**
+ * Adds a new sticker to a set (https://core.telegram.org/bots/api#addStickerToSet)
+ * @param addStickerToSet Information of the sticker to set
+ * @return If success, true is returned
+ */
+ public abstract CompletableFuture executeAsync(AddStickerToSet addStickerToSet);
+
+ /**
+ * Set sticker set thumb (https://core.telegram.org/bots/api#setStickerSetThumb)
+ * @param setStickerSetThumb Information of the sticker to set
+ * @return If success, true is returned
+ */
+ public abstract CompletableFuture executeAsync(SetStickerSetThumb setStickerSetThumb);
+
+ /**
+ * Creates a new sticker set (https://core.telegram.org/bots/api#createNewStickerSet)
+ * @param createNewStickerSet Information of the sticker set to create
+ * @return If success, true is returned
+ */
+ public abstract CompletableFuture executeAsync(CreateNewStickerSet createNewStickerSet);
+
+ /**
+ * Upload a new file as sticker (https://core.telegram.org/bots/api#uploadStickerFile)
+ * @param uploadStickerFile Information of the file to upload as sticker
+ * @return If success, true is returned
+ */
+ public abstract CompletableFuture executeAsync(UploadStickerFile uploadStickerFile);
+
+ /**
+ * Edit media in a message
+ * @param editMessageMedia Information of the new media
+ * @return If the edited message is not an inline message, the edited Message is returned, otherwise True is returned
+ */
+ public abstract CompletableFuture executeAsync(EditMessageMedia editMessageMedia);
+
+ /**
+ * Send animation
+ * @param sendAnimation Information of the animation
+ * @return Sent message
+ */
+ public abstract CompletableFuture executeAsync(SendAnimation sendAnimation);
+
// Simplified methods
protected abstract , Callback extends SentCallback> void sendApiMethodAsync(Method method, Callback callback);
+ protected abstract > CompletableFuture sendApiMethodAsync(Method method);
+
protected abstract > T sendApiMethod(Method method) throws TelegramApiException;
}
diff --git a/telegrambots/src/main/java/org/telegram/telegrambots/bots/DefaultAbsSender.java b/telegrambots/src/main/java/org/telegram/telegrambots/bots/DefaultAbsSender.java
index 97b3c065..2f72f236 100644
--- a/telegrambots/src/main/java/org/telegram/telegrambots/bots/DefaultAbsSender.java
+++ b/telegrambots/src/main/java/org/telegram/telegrambots/bots/DefaultAbsSender.java
@@ -2,6 +2,7 @@ package org.telegram.telegrambots.bots;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
@@ -50,6 +51,7 @@ import java.io.Serializable;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -61,6 +63,7 @@ import static org.telegram.telegrambots.Constants.SOCKET_TIMEOUT;
* Implementation of all the methods needed to interact with Telegram Servers
*/
@SuppressWarnings({"unused"})
+@Slf4j
public abstract class DefaultAbsSender extends AbsSender {
private static final ContentType TEXT_PLAIN_CONTENT_TYPE = ContentType.create("text/plain", StandardCharsets.UTF_8);
@@ -92,22 +95,6 @@ public abstract class DefaultAbsSender extends AbsSender {
}
}
- private void configureHttpContext() {
-
- if (options.getProxyType() != DefaultBotOptions.ProxyType.NO_PROXY) {
- InetSocketAddress socksaddr = new InetSocketAddress(options.getProxyHost(), options.getProxyPort());
- options.getHttpContext().setAttribute("socketAddress", socksaddr);
- }
-
- if (options.getProxyType() == DefaultBotOptions.ProxyType.SOCKS4) {
- options.getHttpContext().setAttribute("socksVersion", 4);
- }
- if (options.getProxyType() == DefaultBotOptions.ProxyType.SOCKS5) {
- options.getHttpContext().setAttribute("socksVersion", 5);
- }
-
- }
-
/**
* Returns the token of the bot to be able to perform Telegram Api Requests
* @return Token of the bot
@@ -118,6 +105,10 @@ public abstract class DefaultAbsSender extends AbsSender {
return options;
}
+ public String getBaseUrl() {
+ return options.getBaseUrl() + getBotToken() + "/";
+ }
+
// Send Requests
public final java.io.File downloadFile(String filePath) throws TelegramApiException {
@@ -776,6 +767,204 @@ public abstract class DefaultAbsSender extends AbsSender {
}
}
+ // Async Methods
+
+ @Override
+ public CompletableFuture executeAsync(SendDocument sendDocument) {
+ CompletableFuture completableFuture = new CompletableFuture<>();
+ exe.submit(() -> {
+ try {
+ completableFuture.complete(execute(sendDocument));
+ } catch (TelegramApiException e) {
+ completableFuture.completeExceptionally(e);
+ }
+ });
+ return completableFuture;
+ }
+
+ @Override
+ public CompletableFuture executeAsync(SendPhoto sendPhoto) {
+ CompletableFuture completableFuture = new CompletableFuture<>();
+ exe.submit(() -> {
+ try {
+ completableFuture.complete(execute(sendPhoto));
+ } catch (TelegramApiException e) {
+ completableFuture.completeExceptionally(e);
+ }
+ });
+ return completableFuture;
+ }
+
+ @Override
+ public CompletableFuture executeAsync(SendVideo sendVideo) {
+ CompletableFuture completableFuture = new CompletableFuture<>();
+ exe.submit(() -> {
+ try {
+ completableFuture.complete(execute(sendVideo));
+ } catch (TelegramApiException e) {
+ completableFuture.completeExceptionally(e);
+ }
+ });
+ return completableFuture;
+ }
+
+ @Override
+ public CompletableFuture executeAsync(SendVideoNote sendVideoNote) {
+ CompletableFuture completableFuture = new CompletableFuture<>();
+ exe.submit(() -> {
+ try {
+ completableFuture.complete(execute(sendVideoNote));
+ } catch (TelegramApiException e) {
+ completableFuture.completeExceptionally(e);
+ }
+ });
+ return completableFuture;
+ }
+
+ @Override
+ public CompletableFuture executeAsync(SendSticker sendSticker) {
+ CompletableFuture completableFuture = new CompletableFuture<>();
+ exe.submit(() -> {
+ try {
+ completableFuture.complete(execute(sendSticker));
+ } catch (TelegramApiException e) {
+ completableFuture.completeExceptionally(e);
+ }
+ });
+ return completableFuture;
+ }
+
+ @Override
+ public CompletableFuture executeAsync(SendAudio sendAudio) {
+ CompletableFuture completableFuture = new CompletableFuture<>();
+ exe.submit(() -> {
+ try {
+ completableFuture.complete(execute(sendAudio));
+ } catch (TelegramApiException e) {
+ completableFuture.completeExceptionally(e);
+ }
+ });
+ return completableFuture;
+ }
+
+ @Override
+ public CompletableFuture executeAsync(SendVoice sendVoice) {
+ CompletableFuture completableFuture = new CompletableFuture<>();
+ exe.submit(() -> {
+ try {
+ completableFuture.complete(execute(sendVoice));
+ } catch (TelegramApiException e) {
+ completableFuture.completeExceptionally(e);
+ }
+ });
+ return completableFuture;
+ }
+
+ @Override
+ public CompletableFuture> executeAsync(SendMediaGroup sendMediaGroup) {
+ CompletableFuture> completableFuture = new CompletableFuture<>();
+ exe.submit(() -> {
+ try {
+ completableFuture.complete(execute(sendMediaGroup));
+ } catch (TelegramApiException e) {
+ completableFuture.completeExceptionally(e);
+ }
+ });
+ return completableFuture;
+ }
+
+ @Override
+ public CompletableFuture executeAsync(SetChatPhoto setChatPhoto) {
+ CompletableFuture completableFuture = new CompletableFuture<>();
+ exe.submit(() -> {
+ try {
+ completableFuture.complete(execute(setChatPhoto));
+ } catch (TelegramApiException e) {
+ completableFuture.completeExceptionally(e);
+ }
+ });
+ return completableFuture;
+ }
+
+ @Override
+ public CompletableFuture executeAsync(AddStickerToSet addStickerToSet) {
+ CompletableFuture completableFuture = new CompletableFuture<>();
+ exe.submit(() -> {
+ try {
+ completableFuture.complete(execute(addStickerToSet));
+ } catch (TelegramApiException e) {
+ completableFuture.completeExceptionally(e);
+ }
+ });
+ return completableFuture;
+ }
+
+ @Override
+ public CompletableFuture executeAsync(SetStickerSetThumb setStickerSetThumb) {
+ CompletableFuture completableFuture = new CompletableFuture<>();
+ exe.submit(() -> {
+ try {
+ completableFuture.complete(execute(setStickerSetThumb));
+ } catch (TelegramApiException e) {
+ completableFuture.completeExceptionally(e);
+ }
+ });
+ return completableFuture;
+ }
+
+ @Override
+ public CompletableFuture executeAsync(CreateNewStickerSet createNewStickerSet) {
+ CompletableFuture completableFuture = new CompletableFuture<>();
+ exe.submit(() -> {
+ try {
+ completableFuture.complete(execute(createNewStickerSet));
+ } catch (TelegramApiException e) {
+ completableFuture.completeExceptionally(e);
+ }
+ });
+ return completableFuture;
+ }
+
+ @Override
+ public CompletableFuture executeAsync(UploadStickerFile uploadStickerFile) {
+ CompletableFuture completableFuture = new CompletableFuture<>();
+ exe.submit(() -> {
+ try {
+ completableFuture.complete(execute(uploadStickerFile));
+ } catch (TelegramApiException e) {
+ completableFuture.completeExceptionally(e);
+ }
+ });
+ return completableFuture;
+ }
+
+ @Override
+ public CompletableFuture executeAsync(EditMessageMedia editMessageMedia) {
+ CompletableFuture completableFuture = new CompletableFuture<>();
+ exe.submit(() -> {
+ try {
+ completableFuture.complete(execute(editMessageMedia));
+ } catch (TelegramApiException e) {
+ completableFuture.completeExceptionally(e);
+ }
+ });
+ return completableFuture;
+ }
+
+ @Override
+ public CompletableFuture executeAsync(SendAnimation sendAnimation) {
+ CompletableFuture completableFuture = new CompletableFuture<>();
+ exe.submit(() -> {
+ try {
+ completableFuture.complete(execute(sendAnimation));
+ } catch (TelegramApiException e) {
+ completableFuture.completeExceptionally(e);
+ }
+ });
+ return completableFuture;
+ }
+
+
// Simplified methods
@Override
@@ -799,6 +988,20 @@ public abstract class DefaultAbsSender extends AbsSender {
});
}
+ @Override
+ protected > CompletableFuture sendApiMethodAsync(Method method) {
+ CompletableFuture completableFuture = new CompletableFuture<>();
+ exe.submit(() -> {
+ try {
+ String responseContent = sendMethodRequest(method);
+ completableFuture.complete(method.deserializeResponse(responseContent));
+ } catch (IOException | TelegramApiValidationException | TelegramApiRequestException e) {
+ completableFuture.completeExceptionally(e);
+ }
+ });
+ return completableFuture;
+ }
+
@Override
protected final > T sendApiMethod(Method method) throws TelegramApiException {
try {
@@ -809,6 +1012,24 @@ public abstract class DefaultAbsSender extends AbsSender {
}
}
+ // Private methods
+
+ private void configureHttpContext() {
+
+ if (options.getProxyType() != DefaultBotOptions.ProxyType.NO_PROXY) {
+ InetSocketAddress socksaddr = new InetSocketAddress(options.getProxyHost(), options.getProxyPort());
+ options.getHttpContext().setAttribute("socketAddress", socksaddr);
+ }
+
+ if (options.getProxyType() == DefaultBotOptions.ProxyType.SOCKS4) {
+ options.getHttpContext().setAttribute("socksVersion", 4);
+ }
+ if (options.getProxyType() == DefaultBotOptions.ProxyType.SOCKS5) {
+ options.getHttpContext().setAttribute("socksVersion", 5);
+ }
+
+ }
+
private > String sendMethodRequest(Method method) throws TelegramApiValidationException, IOException {
method.validate();
String url = getBaseUrl() + method.getMethod();
@@ -888,10 +1109,6 @@ public abstract class DefaultAbsSender extends AbsSender {
}
}
- public String getBaseUrl() {
- return options.getBaseUrl() + getBotToken() + "/";
- }
-
private void assertParamNotNull(Object param, String paramName) throws TelegramApiException {
if (param == null) {
throw new TelegramApiException("Parameter " + paramName + " can not be null");