Move TelegramFileDownloader and finish implementation

The fileDownloader now offers all necessary methods. Still needs some
polishing
This commit is contained in:
chase 2019-03-26 22:39:36 +01:00
parent a317001d4b
commit ef0d78eb4c
4 changed files with 205 additions and 165 deletions

View File

@ -2,7 +2,6 @@ package org.telegram.telegrambots.bots;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.io.FileUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
@ -14,6 +13,7 @@ import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.telegram.telegrambots.facilities.TelegramHttpClientBuilder;
import org.telegram.telegrambots.facilities.filedownloader.TelegramFileDownloader;
import org.telegram.telegrambots.meta.api.methods.BotApiMethod;
import org.telegram.telegrambots.meta.api.methods.groupadministration.SetChatPhoto;
import org.telegram.telegrambots.meta.api.methods.send.*;
@ -36,10 +36,9 @@ import org.telegram.telegrambots.meta.updateshandlers.DownloadFileCallback;
import org.telegram.telegrambots.meta.updateshandlers.SentCallback;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.ExecutorService;
@ -61,6 +60,7 @@ public abstract class DefaultAbsSender extends AbsSender {
private final DefaultBotOptions options;
private volatile CloseableHttpClient httpClient;
private volatile RequestConfig requestConfig;
private final TelegramFileDownloader telegramFileDownloader = new TelegramFileDownloader(this::getBotToken);
protected DefaultAbsSender(DefaultBotOptions options) {
super();
@ -109,37 +109,35 @@ public abstract class DefaultAbsSender extends AbsSender {
// Send Requests
public final java.io.File downloadFile(String filePath) throws TelegramApiException {
if(filePath == null || filePath.isEmpty()){
throw new TelegramApiException("Parameter file can not be null");
}
String url = File.getFileUrl(getBotToken(), filePath);
String tempFileName = Long.toString(System.currentTimeMillis());
return downloadToTemporaryFileWrappingExceptions(url, tempFileName);
return telegramFileDownloader.downloadFile(filePath);
}
public final java.io.File downloadFile(File file) throws TelegramApiException {
assertParamNotNull(file, "file");
String url = file.getFileUrl(getBotToken());
String tempFileName = file.getFileId();
return downloadToTemporaryFileWrappingExceptions(url, tempFileName);
return telegramFileDownloader.downloadFile(file);
}
public final java.io.File downloadFile(File file, java.io.File outputFile) throws TelegramApiException {
return telegramFileDownloader.downloadFile(file, outputFile);
}
public final java.io.File downloadFile(String filePath, java.io.File outputFile) throws TelegramApiException {
return telegramFileDownloader.downloadFile(filePath, outputFile);
}
public final void downloadFileAsync(String filePath, DownloadFileCallback<String> callback) throws TelegramApiException {
if(filePath == null || filePath.isEmpty()){
throw new TelegramApiException("Parameter filePath can not be null");
}
assertParamNotNull(callback, "callback");
String url = File.getFileUrl(getBotToken(), filePath);
String tempFileName = Long.toString(System.currentTimeMillis());
exe.submit(getDownloadFileAsyncJob(filePath, callback, url, tempFileName));
telegramFileDownloader.downloadFileAsync(filePath, callback);
}
public final void downloadFileAsync(File file, DownloadFileCallback<File> callback) throws TelegramApiException {
assertParamNotNull(file, "file");
assertParamNotNull(callback, "callback");
String url = file.getFileUrl(getBotToken());
String tempFileName = file.getFileId();
exe.submit(getDownloadFileAsyncJob(file, callback, url, tempFileName));
telegramFileDownloader.downloadFileAsync(file, callback);
}
public final InputStream downloadFileAsStream(String filePath) throws TelegramApiException {
return telegramFileDownloader.downloadFileAsStream(filePath);
}
public final InputStream downloadFileAsStream(File file) throws TelegramApiException {
return telegramFileDownloader.downloadFileAsStream(file);
}
// Specific Send Requests
@ -720,38 +718,6 @@ public abstract class DefaultAbsSender extends AbsSender {
}
}
private <T> Runnable getDownloadFileAsyncJob(T fileIdentifier, DownloadFileCallback<T> callback, String url, String tempFileName) {
//noinspection Convert2Lambda
return new Runnable() {
@Override
public void run() {
try {
callback.onResult(fileIdentifier, downloadToTemporaryFile(url, tempFileName));
} catch (MalformedURLException e) {
callback.onException(fileIdentifier, new TelegramApiException("Wrong url for file: " + url));
} catch (IOException e) {
callback.onException(fileIdentifier, new TelegramApiRequestException("Error downloading the file", e));
}
}
};
}
private java.io.File downloadToTemporaryFileWrappingExceptions(String url, String tempFileName) throws TelegramApiException {
try {
return downloadToTemporaryFile(url, tempFileName);
} catch (MalformedURLException e) {
throw new TelegramApiException("Wrong url for file: " + url);
} catch (IOException e) {
throw new TelegramApiRequestException("Error downloading the file", e);
}
}
private java.io.File downloadToTemporaryFile(String url, String tempFileName) throws IOException {
java.io.File output = java.io.File.createTempFile(tempFileName, ".tmp");
FileUtils.copyURLToFile(new URL(url), output);
return output;
}
private <T extends Serializable, Method extends BotApiMethod<T>> String sendMethodRequest(Method method) throws TelegramApiValidationException, IOException {
method.validate();
String url = getBaseUrl() + method.getMethod();

View File

@ -1,108 +0,0 @@
package org.telegram.telegrambots.facilities;
import org.apache.commons.io.FileUtils;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.telegram.telegrambots.bots.DefaultAbsSender;
import org.telegram.telegrambots.meta.api.objects.File;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;
import org.telegram.telegrambots.meta.updateshandlers.DownloadFileCallback;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.concurrent.ExecutorService;
@SuppressWarnings("Duplicates")
public class TelegramFileDownloader {
private DefaultAbsSender sender;
ExecutorService exe;
CloseableHttpClient httpClient = HttpClients.createDefault();
public final java.io.File downloadFile(String filePath) throws TelegramApiException {
if (filePath == null || filePath.isEmpty()) {
throw new TelegramApiException("Parameter file can not be null");
}
String url = File.getFileUrl(sender.getBotToken(), filePath);
String tempFileName = Long.toString(System.currentTimeMillis());
return downloadToTemporaryFileWrappingExceptions(url, tempFileName);
}
public final java.io.File downloadFile(File file) throws TelegramApiException {
assertParamNotNull(file, "file");
String url = file.getFileUrl(sender.getBotToken());
String tempFileName = file.getFileId();
return downloadToTemporaryFileWrappingExceptions(url, tempFileName);
}
public final void downloadFileAsync(String filePath, DownloadFileCallback<String> callback) throws TelegramApiException {
if (filePath == null || filePath.isEmpty()) {
throw new TelegramApiException("Parameter filePath can not be null");
}
assertParamNotNull(callback, "callback");
String url = File.getFileUrl(sender.getBotToken(), filePath);
String tempFileName = Long.toString(System.currentTimeMillis());
exe.submit(getDownloadFileAsyncJob(filePath, callback, url, tempFileName));
}
public final void downloadFileAsync(File file, DownloadFileCallback<File> callback) throws TelegramApiException {
assertParamNotNull(file, "file");
assertParamNotNull(callback, "callback");
String url = file.getFileUrl(sender.getBotToken());
String tempFileName = file.getFileId();
exe.submit(getDownloadFileAsyncJob(file, callback, url, tempFileName));
}
private <T> Runnable getDownloadFileAsyncJob(T fileIdentifier, DownloadFileCallback<T> callback, String url, String tempFileName) {
//noinspection Convert2Lambda
return new Runnable() {
@Override
public void run() {
try {
callback.onResult(fileIdentifier, downloadToTemporaryFile(url, tempFileName));
} catch (MalformedURLException e) {
callback.onException(fileIdentifier, new TelegramApiException("Wrong url for file: " + url));
} catch (IOException e) {
callback.onException(fileIdentifier, new TelegramApiRequestException("Error downloading the file", e));
}
}
};
}
private java.io.File downloadToTemporaryFileWrappingExceptions(String url, String tempFileName) throws TelegramApiException {
try {
return downloadToTemporaryFile(url, tempFileName);
} catch (MalformedURLException e) {
throw new TelegramApiException("Wrong url for file: " + url);
} catch (IOException e) {
throw new TelegramApiRequestException("Error downloading the file", e);
}
}
private java.io.File downloadToTemporaryFile(String url, String tempFileName) throws IOException {
final java.io.File output = java.io.File.createTempFile(tempFileName, ".tmp");
final HttpGet get = new HttpGet(url);
final HttpResponse response = httpClient.execute(get);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_OK) {
final InputStream content = response.getEntity().getContent();
FileUtils.copyInputStreamToFile(content, output);
} else {
throw new IOException("Unexpected Status code. Expected 200 got + statusCode");
}
return output;
}
private void assertParamNotNull(Object param, String paramName) throws TelegramApiException {
if (param == null) {
throw new TelegramApiException("Parameter " + paramName + " can not be null");
}
}
}

View File

@ -0,0 +1,10 @@
package org.telegram.telegrambots.facilities.filedownloader;
/**
* Runtime Exception to wrap Exceptions thrown during file download
*/
public class DownloadFileException extends RuntimeException {
public DownloadFileException(final String message, final Throwable e) {
super(message, e);
}
}

View File

@ -0,0 +1,172 @@
package org.telegram.telegrambots.facilities.filedownloader;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.telegram.telegrambots.meta.api.objects.File;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import org.telegram.telegrambots.meta.updateshandlers.DownloadFileCallback;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import java.util.function.Supplier;
import static org.apache.commons.io.FileUtils.copyInputStreamToFile;
import static org.apache.http.HttpStatus.SC_OK;
/**
* Wraps the file downloading code into one class.
* @author Chase22
* @version 1.0
*/
public class TelegramFileDownloader {
private final HttpClient httpClient;
private final Supplier<String> botTokenSupplier;
public TelegramFileDownloader(final Supplier<String> botTokenSupplier) {
this.botTokenSupplier = botTokenSupplier;
httpClient = HttpClients.createDefault();
}
public TelegramFileDownloader(final HttpClient httpClient, final Supplier<String> botTokenSupplier) {
this.httpClient = httpClient;
this.botTokenSupplier = botTokenSupplier;
}
public final java.io.File downloadFile(String filePath) throws TelegramApiException {
String tempFileName = Long.toString(System.currentTimeMillis());
return downloadFile(filePath, getTempFile(tempFileName));
}
public final java.io.File downloadFile(File file) throws TelegramApiException {
return downloadFile(file, getTempFile(file.getFileId()));
}
public final java.io.File downloadFile(File file, java.io.File outputFile) throws TelegramApiException {
if (file == null) {
throw new TelegramApiException("Parameter file can not be null");
}
String url = file.getFileUrl(botTokenSupplier.get());
return downloadToFile(url, outputFile);
}
public final java.io.File downloadFile(String filePath, java.io.File outputFile) throws TelegramApiException {
if (filePath == null || filePath.isEmpty()) {
throw new TelegramApiException("Parameter file can not be null");
}
String url = File.getFileUrl(botTokenSupplier.get(), filePath);
return downloadToFile(url, outputFile);
}
public final InputStream downloadFileAsStream(String filePath) throws TelegramApiException {
try {
return getFileDownloadStreamFuture(File.getFileUrl(botTokenSupplier.get(), filePath)).get();
} catch (InterruptedException e) {
throw new TelegramApiException("Error downloading file", e);
} catch (ExecutionException e) {
throw new TelegramApiException("Error downloading file", e.getCause());
}
}
public final InputStream downloadFileAsStream(File file) throws TelegramApiException {
try {
return getFileDownloadStreamFuture(file.getFileUrl(botTokenSupplier.get())).get();
} catch (InterruptedException e) {
throw new TelegramApiException("Error downloading file", e);
} catch (ExecutionException e) {
throw new TelegramApiException("Error downloading file", e.getCause());
}
}
public final void downloadFileAsync(String filePath, DownloadFileCallback<String> callback) throws TelegramApiException {
if (filePath == null || filePath.isEmpty()) {
throw new TelegramApiException("Parameter filePath can not be null");
}
if (callback == null) {
throw new TelegramApiException("Parameter callback can not be null");
}
String url = File.getFileUrl(botTokenSupplier.get(), filePath);
String tempFileName = Long.toString(System.currentTimeMillis());
getFileDownloadFuture(url, getTempFile(tempFileName))
.thenAccept(output -> callback.onResult(filePath, output))
.exceptionally(throwable -> {
// Unwrap java.util.concurrent.CompletionException
if (throwable instanceof CompletionException) {
callback.onException(filePath, new TelegramApiException("Error downloading file", throwable.getCause()));
} else {
callback.onException(filePath, new TelegramApiException("Error downloading file", throwable));
}
return null;
});
}
public final void downloadFileAsync(File file, DownloadFileCallback<File> callback) throws TelegramApiException {
if (file == null) {
throw new TelegramApiException("Parameter file can not be null");
}
if (callback == null) {
throw new TelegramApiException("Parameter callback can not be null");
}
String url = file.getFileUrl(botTokenSupplier.get());
String tempFileName = file.getFileId();
getFileDownloadFuture(url, getTempFile(tempFileName))
.thenAccept(output -> callback.onResult(file, output))
.exceptionally(throwable -> {
callback.onException(file, new TelegramApiException("Error downloading file", throwable));
return null;
});
}
private java.io.File getTempFile(String tempFileName) throws TelegramApiException {
try {
return java.io.File.createTempFile(tempFileName, ".tmp");
} catch (IOException e) {
throw new TelegramApiException("Error downloading file", e);
}
}
private java.io.File downloadToFile(String url, java.io.File output) throws TelegramApiException {
try {
return getFileDownloadFuture(url, output).get();
} catch (InterruptedException e) {
throw new TelegramApiException("File Download got interrupted", e);
} catch (ExecutionException e) {
throw new TelegramApiException("Error downloading file", e.getCause());
}
}
private CompletableFuture<java.io.File> getFileDownloadFuture(String url, java.io.File output) {
return getFileDownloadStreamFuture(url).thenApply(stream -> {
try {
copyInputStreamToFile(stream, output);
return output;
} catch (IOException e) {
throw new DownloadFileException("Error writing downloaded file", e);
}
});
}
private CompletableFuture<InputStream> getFileDownloadStreamFuture(final String url) {
return CompletableFuture.supplyAsync(() -> {
try {
HttpResponse response = httpClient.execute(new HttpGet(url));
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == SC_OK) {
return response.getEntity().getContent();
} else {
throw new TelegramApiException("Unexpected Status code while downloading file. Expected 200 got " + statusCode);
}
} catch (IOException | TelegramApiException e) {
throw new DownloadFileException("Error downloading file", e);
}
});
}
}