diff --git a/.gitignore b/.gitignore index 8a74bebb..e3308905 100644 --- a/.gitignore +++ b/.gitignore @@ -22,10 +22,6 @@ buildNumber.properties # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* -# unneeded files -.idea/dataSources.* -.idea/workspace.xml - # logs files *.log diff --git a/README.md b/README.md index 629c497f..9044d322 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ I recommend using getUpdates methods. ## Usage -Just import add the library to your project using [Maven, Gradly, ...](https://jitpack.io/#rubenlagus/TelegramBots/v2.3.2) or download the jar(including all dependencies) from [here](https://github.com/rubenlagus/TelegramBots/releases/tag/v2.3.2) +Just import add the library to your project using [Maven, Gradly, ...](https://jitpack.io/#rubenlagus/TelegramBots/v2.3.3) or download the jar(including all dependencies) from [here](https://github.com/rubenlagus/TelegramBots/releases/tag/v2.3.3) In order to use Long Polling mode, just create your own bot extending `org.telegram.telegrambots.bots.TelegramLongPollingBot`. diff --git a/pom.xml b/pom.xml index 860b1770..7c91bea0 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ jar org.telegram telegrambots - 2.3.2 + 2.3.3 Telegram Bots https://telegram.me/JavaBotsApi @@ -22,7 +22,7 @@ UTF-8 UTF-8 - 2.22.2 + 2.23 1.19.1 4.5.2 20160212 diff --git a/src/main/java/org/telegram/telegrambots/BotLogger.java b/src/main/java/org/telegram/telegrambots/BotLogger.java deleted file mode 100644 index e098f60d..00000000 --- a/src/main/java/org/telegram/telegrambots/BotLogger.java +++ /dev/null @@ -1,355 +0,0 @@ -package org.telegram.telegrambots; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.time.LocalDateTime; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.logging.Handler; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * @author Ruben Bermudez - * @version 2.0 - * @brief Logger to file - * @date 21/01/15 - */ -public class BotLogger { - private static final Object lockToWrite = new Object(); - private static final String pathToLogs = "./"; - private static final Logger logger = Logger.getLogger("Telegram Bots Api"); - private static final ConcurrentLinkedQueue logsToFile = new ConcurrentLinkedQueue<>(); - private static volatile PrintWriter logginFile; - private static volatile String currentFileName; - private static volatile LocalDateTime lastFileDate; - private static LoggerThread loggerThread = new LoggerThread(); - - static { - logger.setLevel(Level.OFF); - loggerThread.start(); - lastFileDate = LocalDateTime.now(); - if ((currentFileName == null) || (currentFileName.compareTo("") == 0)) { - currentFileName = pathToLogs + dateFormatterForFileName(lastFileDate) + ".log"; - try { - final File file = new File(currentFileName); - if (file.exists()) { - logginFile = new PrintWriter(new BufferedWriter(new FileWriter(currentFileName, true))); - } else { - final boolean created = file.createNewFile(); - if (created) { - logginFile = new PrintWriter(new BufferedWriter(new FileWriter(currentFileName, true))); - } else { - throw new NullPointerException("File for logging error"); - } - } - } catch (IOException ignored) { - } - - } - } - - public static void setLevel(Level level) { - logger.setLevel(level); - } - - public static void registerLogger(Handler handler) { - logger.addHandler(handler); - } - - public static void log(Level level, String tag, String msg) { - logger.log(level, String.format("[%s] %s", tag, msg)); - logToFile(level, tag, msg); - } - - - public static void severe(String tag, String msg) { - logger.severe(String.format("[%s] %s", tag, msg)); - logToFile(Level.SEVERE, tag, msg); - } - - public static void warn(String tag, String msg) { - warning(tag, msg); - } - - public static void debug(String tag, String msg) { - fine(tag, msg); - } - - public static void error(String tag, String msg) { - severe(tag, msg); - } - - public static void trace(String tag, String msg) { - finer(tag, msg); - } - - public static void warning(String tag, String msg) { - logger.warning(String.format("[%s] %s", tag, msg)); - logToFile(Level.WARNING, tag, msg); - } - - - public static void info(String tag, String msg) { - logger.info(String.format("[%s] %s", tag, msg)); - logToFile(Level.INFO, tag, msg); - } - - - public static void config(String tag, String msg) { - logger.config(String.format("[%s] %s", tag, msg)); - logToFile(Level.CONFIG, tag, msg); - } - - - public static void fine(String tag, String msg) { - logger.fine(String.format("[%s] %s", tag, msg)); - logToFile(Level.FINE, tag, msg); - } - - - public static void finer(String tag, String msg) { - logger.finer(String.format("[%s] %s", tag, msg)); - logToFile(Level.FINER, tag, msg); - } - - - public static void finest(String tag, String msg) { - logger.finest(String.format("[%s] %s", tag, msg)); - logToFile(Level.FINEST, tag, msg); - } - - - public static void log(Level level, String tag, Throwable throwable) { - logger.log(level, String.format("[%s] Exception", tag), throwable); - logToFile(level, tag, throwable); - } - - public static void log(Level level, String tag, String msg, Throwable thrown) { - logger.log(level, msg, thrown); - logToFile(level, msg, thrown); - } - - public static void severe(String tag, Throwable throwable) { - logToFile(Level.SEVERE, tag, throwable); - } - - public static void warning(String tag, Throwable throwable) { - logToFile(Level.WARNING, tag, throwable); - } - - public static void info(String tag, Throwable throwable) { - logToFile(Level.INFO, tag, throwable); - } - - public static void config(String tag, Throwable throwable) { - logToFile(Level.CONFIG, tag, throwable); - } - - public static void fine(String tag, Throwable throwable) { - logToFile(Level.FINE, tag, throwable); - } - - public static void finer(String tag, Throwable throwable) { - logToFile(Level.FINER, tag, throwable); - } - - public static void finest(String tag, Throwable throwable) { - logToFile(Level.FINEST, tag, throwable); - } - - public static void warn(String tag, Throwable throwable) { - warning(tag, throwable); - } - - public static void debug(String tag, Throwable throwable) { - fine(tag, throwable); - } - - public static void error(String tag, Throwable throwable) { - severe(tag, throwable); - } - - public static void trace(String tag, Throwable throwable) { - finer(tag, throwable); - } - - public static void severe(String msg, String tag, Throwable throwable) { - log(Level.SEVERE, tag, msg, throwable); - } - - public static void warning(String msg, String tag, Throwable throwable) { - log(Level.WARNING, tag, msg, throwable); - } - - public static void info(String msg, String tag, Throwable throwable) { - log(Level.INFO, tag, msg, throwable); - } - - public static void config(String msg, String tag, Throwable throwable) { - log(Level.CONFIG, tag, msg, throwable); - } - - public static void fine(String msg, String tag, Throwable throwable) { - log(Level.FINE, tag, msg, throwable); - } - - public static void finer(String msg, String tag, Throwable throwable) { - log(Level.FINER, tag, msg, throwable); - } - - public static void finest(String msg, String tag, Throwable throwable) { - log(Level.FINEST, msg, throwable); - } - - public static void warn(String msg, String tag, Throwable throwable) { - log(Level.WARNING, tag, msg, throwable); - } - - public static void debug(String msg, String tag, Throwable throwable) { - log(Level.FINE, tag, msg, throwable); - } - - public static void error(String msg, String tag, Throwable throwable) { - log(Level.SEVERE, tag, msg, throwable); - } - - public static void trace(String msg, String tag, Throwable throwable) { - log(Level.FINER, tag, msg, throwable); - } - - private static boolean isCurrentDate(LocalDateTime dateTime) { - return dateTime.toLocalDate().isEqual(lastFileDate.toLocalDate()); - } - - private static String dateFormatterForFileName(LocalDateTime dateTime) { - String dateString = ""; - dateString += dateTime.getDayOfMonth(); - dateString += dateTime.getMonthValue(); - dateString += dateTime.getYear(); - return dateString; - } - - private static String dateFormatterForLogs(LocalDateTime dateTime) { - String dateString = "["; - dateString += dateTime.getDayOfMonth() + "_"; - dateString += dateTime.getMonthValue() + "_"; - dateString += dateTime.getYear() + "_"; - dateString += dateTime.getHour() + ":"; - dateString += dateTime.getMinute() + ":"; - dateString += dateTime.getSecond(); - dateString += "] "; - return dateString; - } - - private static void updateAndCreateFile(LocalDateTime dateTime) { - if (!isCurrentDate(dateTime)) { - lastFileDate = LocalDateTime.now(); - currentFileName = pathToLogs + dateFormatterForFileName(lastFileDate) + ".log"; - try { - logginFile.flush(); - logginFile.close(); - final File file = new File(currentFileName); - if (file.exists()) { - logginFile = new PrintWriter(new BufferedWriter(new FileWriter(currentFileName, true))); - } else { - final boolean created = file.createNewFile(); - if (created) { - logginFile = new PrintWriter(new BufferedWriter(new FileWriter(currentFileName, true))); - } else { - throw new NullPointerException("Error updating log file"); - } - } - } catch (IOException ignored) { - } - } - } - - - private static void logToFile(Level level, String tag, Throwable throwable) { - if (isLoggable(level)) { - synchronized (lockToWrite) { - final LocalDateTime currentDate = LocalDateTime.now(); - final String dateForLog = dateFormatterForLogs(currentDate); - updateAndCreateFile(currentDate); - logThrowableToFile(level, tag, throwable, dateForLog); - } - } - } - - - private static void logToFile(Level level, String tag, String msg) { - if (isLoggable(level)) { - synchronized (lockToWrite) { - final LocalDateTime currentDate = LocalDateTime.now(); - updateAndCreateFile(currentDate); - final String dateForLog = dateFormatterForLogs(currentDate); - logMsgToFile(level, tag, msg, dateForLog); - } - } - } - - private static void logToFile(Level level, String tag, String msg, Throwable throwable) { - if (isLoggable(level)) { - synchronized (lockToWrite) { - final LocalDateTime currentDate = LocalDateTime.now(); - updateAndCreateFile(currentDate); - final String dateForLog = dateFormatterForLogs(currentDate); - logMsgToFile(level, tag, msg, dateForLog); - logThrowableToFile(level, tag, throwable, dateForLog); - } - } - } - - private static void logMsgToFile(Level level, String tag, String msg, String dateForLog) { - final String logMessage = String.format("%s{%s} %s - %s", dateForLog, level.toString(), tag, msg); - logsToFile.add(logMessage); - synchronized (logsToFile) { - logsToFile.notifyAll(); - } - } - - private static void logThrowableToFile(Level level, String tag, Throwable throwable, String dateForLog) { - String throwableLog = String.format("%s{%s} %s - %s", dateForLog, level.toString(), tag, throwable.toString()); - for (StackTraceElement element : throwable.getStackTrace()) { - throwableLog += "\tat " + element + "\n"; - } - logsToFile.add(throwableLog); - synchronized (logsToFile) { - logsToFile.notifyAll(); - } - } - - private static boolean isLoggable(Level level) { - return logger.isLoggable(level); - } - - private static class LoggerThread extends Thread { - - @Override - public void run() { - while (true) { - final ConcurrentLinkedQueue stringsToLog = new ConcurrentLinkedQueue<>(); - synchronized (logsToFile) { - if (logsToFile.isEmpty()) { - try { - logsToFile.wait(); - } catch (InterruptedException e) { - return; - } - if (logsToFile.isEmpty()) { - continue; - } - } - stringsToLog.addAll(logsToFile); - logsToFile.clear(); - } - - stringsToLog.stream().forEach(logginFile::println); - logginFile.flush(); - } - } - } -} diff --git a/src/main/java/org/telegram/telegrambots/Constants.java b/src/main/java/org/telegram/telegrambots/Constants.java index bac4a237..60371d0f 100644 --- a/src/main/java/org/telegram/telegrambots/Constants.java +++ b/src/main/java/org/telegram/telegrambots/Constants.java @@ -10,4 +10,6 @@ public class Constants { public static final String BASEURL = "https://api.telegram.org/bot"; public static final String RESPONSEFIELDOK = "ok"; public static final String RESPONSEFIELDRESULT = "result"; + public static final String ERRORDESCRIPTIONFIELD = "description"; + public static final String ERRORCODEFIELD = "error_code"; } diff --git a/src/main/java/org/telegram/telegrambots/TelegramApiException.java b/src/main/java/org/telegram/telegrambots/TelegramApiException.java index 84643e66..d9653b9f 100644 --- a/src/main/java/org/telegram/telegrambots/TelegramApiException.java +++ b/src/main/java/org/telegram/telegrambots/TelegramApiException.java @@ -8,12 +8,13 @@ package org.telegram.telegrambots; */ public class TelegramApiException extends Exception { private String apiResponse = null; + private Integer errorCode; public TelegramApiException(String message) { super(message); } - public TelegramApiException(String message, String apiResponse) { + public TelegramApiException(String message, String apiResponse, Integer errorCode) { super(message); this.apiResponse = apiResponse; } @@ -30,8 +31,10 @@ public class TelegramApiException extends Exception { public String toString() { if (apiResponse == null) { return super.toString(); - } else { + } else if (errorCode == null) { return super.toString() + ": " + apiResponse; + } else { + return super.toString() + ": [" + errorCode + "] " + apiResponse; } } } diff --git a/src/main/java/org/telegram/telegrambots/TelegramBotsApi.java b/src/main/java/org/telegram/telegrambots/TelegramBotsApi.java index 19017ea1..17f37ff2 100644 --- a/src/main/java/org/telegram/telegrambots/TelegramBotsApi.java +++ b/src/main/java/org/telegram/telegrambots/TelegramBotsApi.java @@ -22,6 +22,9 @@ import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; +import static org.telegram.telegrambots.Constants.ERRORCODEFIELD; +import static org.telegram.telegrambots.Constants.ERRORDESCRIPTIONFIELD; + /** * @author Ruben Bermudez * @version 1.0 @@ -94,8 +97,7 @@ public class TelegramBotsApi { * @throws TelegramApiException */ private static void setWebhook(String webHookURL, String botToken, String publicCertificatePath, String publicCertificateName) throws TelegramApiException { - try { - CloseableHttpClient httpclient = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build(); + try (CloseableHttpClient httpclient = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build()) { String url = Constants.BASEURL + botToken + "/" + SetWebhook.PATH; HttpPost httppost = new HttpPost(url); @@ -106,13 +108,14 @@ public class TelegramBotsApi { } HttpEntity multipart = builder.build(); httppost.setEntity(multipart); - CloseableHttpResponse response = httpclient.execute(httppost); - HttpEntity ht = response.getEntity(); - BufferedHttpEntity buf = new BufferedHttpEntity(ht); - String responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); - JSONObject jsonObject = new JSONObject(responseContent); - if (!jsonObject.getBoolean(Constants.RESPONSEFIELDOK)) { - throw new TelegramApiException(webHookURL == null ? "Error removing old webhook" : "Error setting webhook", responseContent); + try (CloseableHttpResponse response = httpclient.execute(httppost)) { + HttpEntity ht = response.getEntity(); + BufferedHttpEntity buf = new BufferedHttpEntity(ht); + String responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); + JSONObject jsonObject = new JSONObject(responseContent); + if (!jsonObject.getBoolean(Constants.RESPONSEFIELDOK)) { + throw new TelegramApiException(webHookURL == null ? "Error removing old webhook" : "Error setting webhook", jsonObject.getString(ERRORDESCRIPTIONFIELD), jsonObject.getInt(ERRORCODEFIELD)); + } } } catch (JSONException e) { throw new TelegramApiException("Error deserializing setWebhook method response", e); diff --git a/src/main/java/org/telegram/telegrambots/api/methods/groupadministration/GetChat.java b/src/main/java/org/telegram/telegrambots/api/methods/groupadministration/GetChat.java new file mode 100644 index 00000000..74e3af2b --- /dev/null +++ b/src/main/java/org/telegram/telegrambots/api/methods/groupadministration/GetChat.java @@ -0,0 +1,79 @@ +package org.telegram.telegrambots.api.methods.groupadministration; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.jsontype.TypeSerializer; + +import org.json.JSONObject; +import org.telegram.telegrambots.Constants; +import org.telegram.telegrambots.api.methods.BotApiMethod; +import org.telegram.telegrambots.api.objects.Chat; + +import java.io.IOException; + +/** + * @author Ruben Bermudez + * @version 1.0 + * @brief Use this method to get information about the chat. Returns Chat object on success. + * @date 20 of May of 2016 + */ +public class GetChat extends BotApiMethod { + public static final String PATH = "getChat"; + + private static final String CHATID_FIELD = "chat_id"; + private String chatId; ///< Unique identifier for the chat to send the message to (Or username for channels) + + public GetChat() { + super(); + } + + public String getChatId() { + return chatId; + } + + public GetChat setChatId(String chatId) { + this.chatId = chatId; + return this; + } + + @Override + public JSONObject toJson() { + JSONObject jsonObject = new JSONObject(); + jsonObject.put(CHATID_FIELD, chatId); + return jsonObject; + } + + @Override + public String getPath() { + return PATH; + } + + @Override + public Chat deserializeResponse(JSONObject answer) { + if (answer.getBoolean(Constants.RESPONSEFIELDOK)) { + return new Chat(answer.getJSONObject(Constants.RESPONSEFIELDRESULT)); + } + return null; + } + + @Override + public void serialize(JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartObject(); + gen.writeStringField(METHOD_FIELD, PATH); + gen.writeStringField(CHATID_FIELD, chatId); + gen.writeEndObject(); + gen.flush(); + } + + @Override + public void serializeWithType(JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) throws IOException { + serialize(gen, serializers); + } + + @Override + public String toString() { + return "GetChat{" + + "chatId='" + chatId + '\'' + + '}'; + } +} diff --git a/src/main/java/org/telegram/telegrambots/api/methods/groupadministration/GetChatAdministrators.java b/src/main/java/org/telegram/telegrambots/api/methods/groupadministration/GetChatAdministrators.java new file mode 100644 index 00000000..cd910ada --- /dev/null +++ b/src/main/java/org/telegram/telegrambots/api/methods/groupadministration/GetChatAdministrators.java @@ -0,0 +1,90 @@ +package org.telegram.telegrambots.api.methods.groupadministration; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.jsontype.TypeSerializer; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.telegram.telegrambots.Constants; +import org.telegram.telegrambots.api.methods.BotApiMethod; +import org.telegram.telegrambots.api.objects.ChatMember; + +import java.io.IOException; +import java.util.ArrayList; + +/** + * @author Ruben Bermudez + * @version 1.0 + * @brief Use this method to get a list of administrators in a chat. + * An Array of ChatMember objects is returned on success, + * containing information about all chat administrators except other bots. + * If the chat is a group or a supergroup and no administrators were appointed, + * only the creator will be returned. + * @date 20 of May of 2016 + */ +public class GetChatAdministrators extends BotApiMethod> { + public static final String PATH = "getChatAdministrators"; + + private static final String CHATID_FIELD = "chat_id"; + private String chatId; ///< Unique identifier for the chat to send the message to (Or username for channels) + + public GetChatAdministrators() { + super(); + } + + public String getChatId() { + return chatId; + } + + public GetChatAdministrators setChatId(String chatId) { + this.chatId = chatId; + return this; + } + + @Override + public JSONObject toJson() { + JSONObject jsonObject = new JSONObject(); + jsonObject.put(CHATID_FIELD, chatId); + return jsonObject; + } + + @Override + public String getPath() { + return PATH; + } + + @Override + public ArrayList deserializeResponse(JSONObject answer) { + if (answer.getBoolean(Constants.RESPONSEFIELDOK)) { + JSONArray admins = answer.getJSONArray(Constants.RESPONSEFIELDRESULT); + ArrayList members = new ArrayList<>(); + for (int i = 0; i < admins.length(); i++) { + members.add(new ChatMember(admins.getJSONObject(i))); + } + return members; + } + return null; + } + + @Override + public void serialize(JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartObject(); + gen.writeStringField(METHOD_FIELD, PATH); + gen.writeStringField(CHATID_FIELD, chatId); + gen.writeEndObject(); + gen.flush(); + } + + @Override + public void serializeWithType(JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) throws IOException { + serialize(gen, serializers); + } + + @Override + public String toString() { + return "GetChatAdministrators{" + + "chatId='" + chatId + '\'' + + '}'; + } +} diff --git a/src/main/java/org/telegram/telegrambots/api/methods/groupadministration/GetChatMember.java b/src/main/java/org/telegram/telegrambots/api/methods/groupadministration/GetChatMember.java new file mode 100644 index 00000000..73648daf --- /dev/null +++ b/src/main/java/org/telegram/telegrambots/api/methods/groupadministration/GetChatMember.java @@ -0,0 +1,94 @@ +package org.telegram.telegrambots.api.methods.groupadministration; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.jsontype.TypeSerializer; + +import org.json.JSONObject; +import org.telegram.telegrambots.Constants; +import org.telegram.telegrambots.api.methods.BotApiMethod; +import org.telegram.telegrambots.api.objects.ChatMember; + +import java.io.IOException; + +/** + * @author Ruben Bermudez + * @version 1.0 + * @brief Use this method to get information about a member of a chat. + * Returns a ChatMember object on success. + * @date 20 of May of 2016 + */ +public class GetChatMember extends BotApiMethod { + public static final String PATH = "getChatAdministrators"; + + private static final String CHATID_FIELD = "chat_id"; + private static final String USERID_FIELD = "user_id"; + private String chatId; ///< Unique identifier for the chat to send the message to (Or username for channels) + private Integer userId; ///< Unique identifier of the target user + + public GetChatMember() { + super(); + } + + public String getChatId() { + return chatId; + } + + public GetChatMember setChatId(String chatId) { + this.chatId = chatId; + return this; + } + + public Integer getUserId() { + return userId; + } + + public GetChatMember setUserId(Integer userId) { + this.userId = userId; + return this; + } + + @Override + public JSONObject toJson() { + JSONObject jsonObject = new JSONObject(); + jsonObject.put(CHATID_FIELD, chatId); + jsonObject.put(USERID_FIELD, userId); + return jsonObject; + } + + @Override + public String getPath() { + return PATH; + } + + @Override + public ChatMember deserializeResponse(JSONObject answer) { + if (answer.getBoolean(Constants.RESPONSEFIELDOK)) { + return new ChatMember(answer.getJSONObject(Constants.RESPONSEFIELDRESULT)); + } + return null; + } + + @Override + public void serialize(JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartObject(); + gen.writeStringField(METHOD_FIELD, PATH); + gen.writeStringField(CHATID_FIELD, chatId); + gen.writeNumberField(USERID_FIELD, userId); + gen.writeEndObject(); + gen.flush(); + } + + @Override + public void serializeWithType(JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) throws IOException { + serialize(gen, serializers); + } + + @Override + public String toString() { + return "GetChatMember{" + + "chatId='" + chatId + '\'' + + ", userId='" + userId + '\'' + + '}'; + } +} diff --git a/src/main/java/org/telegram/telegrambots/api/methods/groupadministration/GetChatMemberCount.java b/src/main/java/org/telegram/telegrambots/api/methods/groupadministration/GetChatMemberCount.java new file mode 100644 index 00000000..3b350902 --- /dev/null +++ b/src/main/java/org/telegram/telegrambots/api/methods/groupadministration/GetChatMemberCount.java @@ -0,0 +1,78 @@ +package org.telegram.telegrambots.api.methods.groupadministration; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.jsontype.TypeSerializer; + +import org.json.JSONObject; +import org.telegram.telegrambots.Constants; +import org.telegram.telegrambots.api.methods.BotApiMethod; + +import java.io.IOException; + +/** + * @author Ruben Bermudez + * @version 1.0 + * @brief Use this method to get the number of members in a chat. Returns Int on success. + * @date 20 of May of 2016 + */ +public class GetChatMemberCount extends BotApiMethod { + public static final String PATH = "getChatAdministrators"; + + private static final String CHATID_FIELD = "chat_id"; + private String chatId; ///< Unique identifier for the chat to send the message to (Or username for channels) + + public GetChatMemberCount() { + super(); + } + + public String getChatId() { + return chatId; + } + + public GetChatMemberCount setChatId(String chatId) { + this.chatId = chatId; + return this; + } + + @Override + public JSONObject toJson() { + JSONObject jsonObject = new JSONObject(); + jsonObject.put(CHATID_FIELD, chatId); + return jsonObject; + } + + @Override + public String getPath() { + return PATH; + } + + @Override + public Integer deserializeResponse(JSONObject answer) { + if (answer.getBoolean(Constants.RESPONSEFIELDOK)) { + return answer.getInt(Constants.RESPONSEFIELDRESULT); + } + return null; + } + + @Override + public void serialize(JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartObject(); + gen.writeStringField(METHOD_FIELD, PATH); + gen.writeStringField(CHATID_FIELD, chatId); + gen.writeEndObject(); + gen.flush(); + } + + @Override + public void serializeWithType(JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) throws IOException { + serialize(gen, serializers); + } + + @Override + public String toString() { + return "GetChatMemberCount{" + + "chatId='" + chatId + '\'' + + '}'; + } +} diff --git a/src/main/java/org/telegram/telegrambots/api/methods/groupadministration/LeaveChat.java b/src/main/java/org/telegram/telegrambots/api/methods/groupadministration/LeaveChat.java new file mode 100644 index 00000000..20fea86c --- /dev/null +++ b/src/main/java/org/telegram/telegrambots/api/methods/groupadministration/LeaveChat.java @@ -0,0 +1,78 @@ +package org.telegram.telegrambots.api.methods.groupadministration; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.jsontype.TypeSerializer; + +import org.json.JSONObject; +import org.telegram.telegrambots.Constants; +import org.telegram.telegrambots.api.methods.BotApiMethod; + +import java.io.IOException; + +/** + * @author Ruben Bermudez + * @version 1.0 + * @brief Use this method for your bot to leave a group, supergroup or channel. Returns True on success. + * @date 20 of May of 2016 + */ +public class LeaveChat extends BotApiMethod { + public static final String PATH = "leaveChat"; + + private static final String CHATID_FIELD = "chat_id"; + private String chatId; ///< Unique identifier for the chat to send the message to (Or username for channels) + + public LeaveChat() { + super(); + } + + public String getChatId() { + return chatId; + } + + public LeaveChat setChatId(String chatId) { + this.chatId = chatId; + return this; + } + + @Override + public JSONObject toJson() { + JSONObject jsonObject = new JSONObject(); + jsonObject.put(CHATID_FIELD, chatId); + return jsonObject; + } + + @Override + public String getPath() { + return PATH; + } + + @Override + public Boolean deserializeResponse(JSONObject answer) { + if (answer.getBoolean(Constants.RESPONSEFIELDOK)) { + return answer.getBoolean(Constants.RESPONSEFIELDRESULT); + } + return null; + } + + @Override + public void serialize(JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartObject(); + gen.writeStringField(METHOD_FIELD, PATH); + gen.writeStringField(CHATID_FIELD, chatId); + gen.writeEndObject(); + gen.flush(); + } + + @Override + public void serializeWithType(JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) throws IOException { + serialize(gen, serializers); + } + + @Override + public String toString() { + return "LeaveChat{" + + "chatId='" + chatId + '\'' + + '}'; + } +} diff --git a/src/main/java/org/telegram/telegrambots/api/methods/send/SendPhoto.java b/src/main/java/org/telegram/telegrambots/api/methods/send/SendPhoto.java index e1059aa0..fcb59daa 100644 --- a/src/main/java/org/telegram/telegrambots/api/methods/send/SendPhoto.java +++ b/src/main/java/org/telegram/telegrambots/api/methods/send/SendPhoto.java @@ -13,7 +13,7 @@ public class SendPhoto { public static final String CHATID_FIELD = "chat_id"; public static final String PHOTO_FIELD = "photo"; - public static final String CAPTION_FIELD = "photo"; + public static final String CAPTION_FIELD = "caption"; public static final String DISABLENOTIFICATION_FIELD = "disable_notification"; public static final String REPLYTOMESSAGEID_FIELD = "reply_to_message_id"; public static final String REPLYMARKUP_FIELD = "reply_markup"; diff --git a/src/main/java/org/telegram/telegrambots/api/objects/ChatMember.java b/src/main/java/org/telegram/telegrambots/api/objects/ChatMember.java new file mode 100644 index 00000000..9a022778 --- /dev/null +++ b/src/main/java/org/telegram/telegrambots/api/objects/ChatMember.java @@ -0,0 +1,58 @@ +package org.telegram.telegrambots.api.objects; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.jsontype.TypeSerializer; + +import org.json.JSONObject; +import org.telegram.telegrambots.api.interfaces.IBotApiObject; + +import java.io.IOException; + +/** + * @author Ruben Bermudez + * @version 1.0 + * @brief This object contains information about one member of the chat. + * @date 20 of May of 2016 + */ +public class ChatMember implements IBotApiObject { + private static final String USER_FIELD = "user"; + private static final String STATUS_FIELD = "status"; + + private User user; ///< Information about the user + private String status; ///< The member's status in the chat. Can be “creator”, “administrator”, “member”, “left” or “kicked” + + public ChatMember(JSONObject object) { + user = new User(object.getJSONObject(USER_FIELD)); + status = object.getString(STATUS_FIELD); + } + + public User getUser() { + return user; + } + + public String getStatus() { + return status; + } + + @Override + public void serialize(JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartObject(); + gen.writeObjectField(USER_FIELD, user); + gen.writeStringField(STATUS_FIELD, status); + gen.writeEndObject(); + } + + @Override + public void serializeWithType(JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) throws IOException { + serialize(gen, serializers); + } + + @Override + public String toString() { + return "ChatMember{" + + "user=" + user + + ", status='" + status + '\'' + + '}'; + } +} diff --git a/src/main/java/org/telegram/telegrambots/api/objects/EntityType.java b/src/main/java/org/telegram/telegrambots/api/objects/EntityType.java index f6308e80..bbf33cb3 100644 --- a/src/main/java/org/telegram/telegrambots/api/objects/EntityType.java +++ b/src/main/java/org/telegram/telegrambots/api/objects/EntityType.java @@ -17,6 +17,7 @@ public class EntityType { public static final String CODE = "code"; ///< Monowidth string public static final String PRE = "pre"; ///< Monowidth block public static final String TEXTLINK = "text_link"; ///< Clickable urls + public static final String TEXTMENTION = "text_mention"; ///< for users without usernames private EntityType() { } diff --git a/src/main/java/org/telegram/telegrambots/api/objects/MemberStatus.java b/src/main/java/org/telegram/telegrambots/api/objects/MemberStatus.java new file mode 100644 index 00000000..3ae2c83c --- /dev/null +++ b/src/main/java/org/telegram/telegrambots/api/objects/MemberStatus.java @@ -0,0 +1,15 @@ +package org.telegram.telegrambots.api.objects; + +/** + * @author Ruben Bermudez + * @version 1.0 + * @brief Group members categories + * @date 22 of May of 2016 + */ +public final class MemberStatus { + public static final String CREATOR = "creator"; + public static final String ADMINISTRATOR = "administrator"; + public static final String MEMBER = "member"; + public static final String LEFT = "left"; + public static final String KICKED = "kicked"; +} diff --git a/src/main/java/org/telegram/telegrambots/api/objects/Message.java b/src/main/java/org/telegram/telegrambots/api/objects/Message.java index 126cb67f..b5029148 100644 --- a/src/main/java/org/telegram/telegrambots/api/objects/Message.java +++ b/src/main/java/org/telegram/telegrambots/api/objects/Message.java @@ -46,10 +46,12 @@ public class Message implements IBotApiObject { private static final String GROUPCHATCREATED_FIELD = "group_chat_created"; private static final String REPLYTOMESSAGE_FIELD = "reply_to_message"; private static final String VOICE_FIELD = "voice"; + private static final String CAPTION_FIELD = "caption"; private static final String SUPERGROUPCREATED_FIELD = "supergroup_chat_created"; private static final String CHANNELCHATCREATED_FIELD = "channel_chat_created"; private static final String MIGRATETOCHAT_FIELD = "migrate_to_chat_id"; private static final String MIGRATEFROMCHAT_FIELD = "migrate_from_chat_id"; + private static final String EDITDATE_FIELD = "edit_date"; @JsonProperty(MESSAGEID_FIELD) private Integer messageId; ///< Integer Unique message identifier @JsonProperty(FROM_FIELD) @@ -61,7 +63,7 @@ public class Message implements IBotApiObject { @JsonProperty(FORWARDFROM_FIELD) private User forwardFrom; ///< Optional. For forwarded messages, sender of the original message @JsonProperty(FORWARDFROMCHAT_FIELD) - private Chat forwardedFromChat; ///< Optional. For messages forwarded from a channel, information about the original channel + private Chat forwardFromChat; ///< Optional. For messages forwarded from a channel, information about the original channel @JsonProperty(FORWARDDATE_FIELD) private Integer forwardDate; ///< Optional. For forwarded messages, date the original message was sent @JsonProperty(TEXT_FIELD) @@ -106,6 +108,8 @@ public class Message implements IBotApiObject { private Message replyToMessage; @JsonProperty(VOICE_FIELD) private Voice voice; ///< Optional. Message is a voice message, information about the file + @JsonProperty(CAPTION_FIELD) + private String caption; ///< Optional. Caption for the document, photo or video, 0-200 characters @JsonProperty(SUPERGROUPCREATED_FIELD) private Boolean superGroupCreated; ///< Optional. Informs that the supergroup has been created @JsonProperty(CHANNELCHATCREATED_FIELD) @@ -114,6 +118,8 @@ public class Message implements IBotApiObject { private Long migrateToChatId; ///< Optional. The chat has been migrated to a chat with specified identifier, not exceeding 1e13 by absolute value @JsonProperty(MIGRATEFROMCHAT_FIELD) private Long migrateFromChatId; ///< Optional. The chat has been migrated from a chat with specified identifier, not exceeding 1e13 by absolute value + @JsonProperty(EDITDATE_FIELD) + private Integer editDate; ///< Optional. Date the message was last edited in Unix time public Message() { super(); @@ -130,7 +136,7 @@ public class Message implements IBotApiObject { } this.chat = new Chat(jsonObject.getJSONObject(CHAT_FIELD)); if (jsonObject.has(FORWARDFROMCHAT_FIELD)) { - this.forwardedFromChat = new Chat(jsonObject.getJSONObject(FORWARDFROMCHAT_FIELD)); + this.forwardFromChat = new Chat(jsonObject.getJSONObject(FORWARDFROMCHAT_FIELD)); } if (jsonObject.has(FORWARDFROM_FIELD)) { this.forwardFrom = new User(jsonObject.getJSONObject(FORWARDFROM_FIELD)); @@ -182,6 +188,9 @@ public class Message implements IBotApiObject { if (jsonObject.has(VOICE_FIELD)) { this.voice = new Voice(jsonObject.getJSONObject(VOICE_FIELD)); } + if (jsonObject.has(CAPTION_FIELD)) { + this.caption = jsonObject.getString(CAPTION_FIELD); + } if (jsonObject.has(NEWCHATMEMBER_FIELD)) { this.newChatMember = new User(jsonObject.getJSONObject(NEWCHATMEMBER_FIELD)); } @@ -219,6 +228,13 @@ public class Message implements IBotApiObject { if (jsonObject.has(MIGRATEFROMCHAT_FIELD)) { this.migrateFromChatId = jsonObject.getLong(MIGRATEFROMCHAT_FIELD); } + if (jsonObject.has(EDITDATE_FIELD)) { + editDate = jsonObject.getInt(EDITDATE_FIELD); + } + + if (hasText() && entities != null) { + entities.forEach(x -> x.computeText(text)); + } } public Integer getMessageId() { @@ -321,6 +337,10 @@ public class Message implements IBotApiObject { return voice; } + public String getCaption() { + return caption; + } + public Boolean getSuperGroupCreated() { return superGroupCreated; } @@ -373,8 +393,12 @@ public class Message implements IBotApiObject { return location != null; } - public Chat getForwardedFromChat() { - return forwardedFromChat; + public Chat getForwardFromChat() { + return forwardFromChat; + } + + public Integer getEditDate() { + return editDate; } @Override @@ -388,8 +412,8 @@ public class Message implements IBotApiObject { gen.writeNumberField(DATE_FIELD, date); } gen.writeObjectField(CHAT_FIELD, chat); - if (forwardedFromChat != null) { - gen.writeObjectField(FORWARDFROMCHAT_FIELD, forwardedFromChat); + if (forwardFromChat != null) { + gen.writeObjectField(FORWARDFROMCHAT_FIELD, forwardFromChat); } if (forwardFrom != null) { gen.writeObjectField(FORWARDFROM_FIELD, forwardFrom); @@ -431,6 +455,9 @@ public class Message implements IBotApiObject { if (voice != null) { gen.writeObjectField(VOICE_FIELD, voice); } + if (caption != null) { + gen.writeObjectField(CAPTION_FIELD, caption); + } if (newChatMember != null) { gen.writeObjectField(NEWCHATMEMBER_FIELD, newChatMember); } @@ -468,6 +495,9 @@ public class Message implements IBotApiObject { if (migrateFromChatId != null) { gen.writeNumberField(MIGRATEFROMCHAT_FIELD, migrateFromChatId); } + if (editDate != null) { + gen.writeNumberField(EDITDATE_FIELD, editDate); + } gen.writeEndObject(); gen.flush(); } @@ -485,7 +515,7 @@ public class Message implements IBotApiObject { ", date=" + date + ", chat=" + chat + ", forwardFrom=" + forwardFrom + - ", forwardedFromChat=" + forwardedFromChat + + ", forwardFromChat=" + forwardFromChat + ", forwardDate=" + forwardDate + ", text='" + text + '\'' + ", audio=" + audio + @@ -504,10 +534,12 @@ public class Message implements IBotApiObject { ", groupchatCreated=" + groupchatCreated + ", replyToMessage=" + replyToMessage + ", voice=" + voice + + ", caption=" + caption + ", superGroupCreated=" + superGroupCreated + ", channelChatCreated=" + channelChatCreated + ", migrateToChatId=" + migrateToChatId + ", migrateFromChatId=" + migrateFromChatId + + ", editDate=" + editDate + '}'; } } diff --git a/src/main/java/org/telegram/telegrambots/api/objects/MessageEntity.java b/src/main/java/org/telegram/telegrambots/api/objects/MessageEntity.java index b436f51f..fc8fefa9 100644 --- a/src/main/java/org/telegram/telegrambots/api/objects/MessageEntity.java +++ b/src/main/java/org/telegram/telegrambots/api/objects/MessageEntity.java @@ -23,6 +23,7 @@ public class MessageEntity implements IBotApiObject { private static final String OFFSET_FIELD = "offset"; private static final String LENGTH_FIELD = "length"; private static final String URL_FIELD = "url"; + private static final String USER_FIELD = "user"; @JsonProperty(TYPE_FIELD) /** * Type of the entity. One of @@ -36,6 +37,7 @@ public class MessageEntity implements IBotApiObject { * code (monowidth string), * pre (monowidth block), * text_link (for clickable text URLs) + * text_mention (for users without usernames) */ private String type; @JsonProperty(OFFSET_FIELD) @@ -44,6 +46,10 @@ public class MessageEntity implements IBotApiObject { private Integer length; ///< Length of the entity in UTF-16 code units @JsonProperty(URL_FIELD) private String url; ///< Optional. For “text_link” only, url that will be opened after user taps on the text + @JsonProperty(USER_FIELD) + private User user; ///< Optional. For “text_mention” only, the mentioned user + + private String text; ///< Text present in the entity. Computed from offset and length public MessageEntity() { super(); @@ -57,6 +63,9 @@ public class MessageEntity implements IBotApiObject { if (EntityType.TEXTLINK.equals(type)) { this.url = jsonObject.getString(URL_FIELD); } + if (EntityType.TEXTMENTION.equals(type)) { + this.user = new User(jsonObject.getJSONObject(USER_FIELD)); + } } public String getType() { @@ -75,6 +84,18 @@ public class MessageEntity implements IBotApiObject { return url; } + public String getText() { + return text; + } + + public User getUser() { + return user; + } + + protected void computeText(String message) { + text = message.substring(offset, offset + length); + } + @Override public void serialize(JsonGenerator gen, SerializerProvider serializers) throws IOException { gen.writeStartObject(); @@ -84,6 +105,9 @@ public class MessageEntity implements IBotApiObject { if (url != null && EntityType.TEXTLINK.equals(type)) { gen.writeStringField(URL_FIELD, url); } + if (user != null && EntityType.TEXTMENTION.equals(type)) { + gen.writeObjectField(USER_FIELD, user); + } gen.writeEndObject(); gen.flush(); } @@ -100,6 +124,7 @@ public class MessageEntity implements IBotApiObject { ", offset=" + offset + ", length=" + length + ", url=" + url + + ", user=" + user + '}'; } } diff --git a/src/main/java/org/telegram/telegrambots/api/objects/Update.java b/src/main/java/org/telegram/telegrambots/api/objects/Update.java index 45cb59ba..a9e271d2 100644 --- a/src/main/java/org/telegram/telegrambots/api/objects/Update.java +++ b/src/main/java/org/telegram/telegrambots/api/objects/Update.java @@ -25,6 +25,7 @@ public class Update implements IBotApiObject { private static final String INLINEQUERY_FIELD = "inline_query"; private static final String CHOSENINLINEQUERY_FIELD = "chosen_inline_result"; private static final String CALLBACKQUERY_FIELD = "callback_query"; + private static final String EDITEDMESSAGE_FIELD = "callback_query"; @JsonProperty(UPDATEID_FIELD) private Integer updateId; @JsonProperty(MESSAGE_FIELD) @@ -35,6 +36,8 @@ public class Update implements IBotApiObject { private ChosenInlineQuery chosenInlineQuery; ///< Optional. The result of a inline query that was chosen by a user and sent to their chat partner @JsonProperty(CALLBACKQUERY_FIELD) private CallbackQuery callbackQuery; ///< Optional. New incoming callback query + @JsonProperty(EDITEDMESSAGE_FIELD) + private Message editedMessage; ///< Optional. New version of a message that is known to the bot and was edited public Update() { super(); @@ -55,6 +58,9 @@ public class Update implements IBotApiObject { if (jsonObject.has(CALLBACKQUERY_FIELD)) { callbackQuery = new CallbackQuery(jsonObject.getJSONObject(CALLBACKQUERY_FIELD)); } + if (jsonObject.has(EDITEDMESSAGE_FIELD)){ + editedMessage = new Message(jsonObject.getJSONObject(EDITEDMESSAGE_FIELD)); + } } public Integer getUpdateId() { @@ -77,6 +83,10 @@ public class Update implements IBotApiObject { return callbackQuery; } + public Message getEditedMessage() { + return editedMessage; + } + public boolean hasMessage() { return message != null; } @@ -93,6 +103,9 @@ public class Update implements IBotApiObject { return callbackQuery != null; } + public boolean hasEditedMessage() { + return editedMessage != null; + } @Override public void serialize(JsonGenerator gen, SerializerProvider serializers) throws IOException { gen.writeStartObject(); @@ -109,6 +122,9 @@ public class Update implements IBotApiObject { if (callbackQuery != null) { gen.writeObjectField(CALLBACKQUERY_FIELD, callbackQuery); } + if (editedMessage != null) { + gen.writeObjectField(EDITEDMESSAGE_FIELD, editedMessage); + } gen.writeEndObject(); gen.flush(); } @@ -126,6 +142,7 @@ public class Update implements IBotApiObject { ", inlineQuery=" + inlineQuery + ", chosenInlineQuery=" + chosenInlineQuery + ", callbackQuery=" + callbackQuery + + ", editedMessage=" + editedMessage + '}'; } } diff --git a/src/main/java/org/telegram/telegrambots/api/objects/inlinequery/result/InlineQueryResultArticle.java b/src/main/java/org/telegram/telegrambots/api/objects/inlinequery/result/InlineQueryResultArticle.java index 65ff5849..3a09675d 100644 --- a/src/main/java/org/telegram/telegrambots/api/objects/inlinequery/result/InlineQueryResultArticle.java +++ b/src/main/java/org/telegram/telegrambots/api/objects/inlinequery/result/InlineQueryResultArticle.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; + import org.json.JSONObject; import org.telegram.telegrambots.api.objects.inlinequery.inputmessagecontent.InputMessageContent; import org.telegram.telegrambots.api.objects.replykeyboard.InlineKeyboardMarkup; @@ -52,7 +53,7 @@ public class InlineQueryResultArticle implements InlineQueryResult { @JsonProperty(THUMBHEIGHT_FIELD) private Integer thumbHeight; ///< Optional. Thumbnail height - public String getType() { + public static String getType() { return type; } @@ -150,8 +151,8 @@ public class InlineQueryResultArticle implements InlineQueryResult { public JSONObject toJson() { JSONObject jsonObject = new JSONObject(); - jsonObject.put(TYPE_FIELD, this.type); - jsonObject.put(ID_FIELD, this.id); + jsonObject.put(TYPE_FIELD, type); + jsonObject.put(ID_FIELD, id); jsonObject.put(TITLE_FIELD, this.title); jsonObject.put(INPUTMESSAGECONTENT_FIELD, inputMessageContent.toJson()); if (replyMarkup != null) { diff --git a/src/main/java/org/telegram/telegrambots/api/objects/inlinequery/result/InlineQueryResultGif.java b/src/main/java/org/telegram/telegrambots/api/objects/inlinequery/result/InlineQueryResultGif.java index cd09d6e7..3cb3db9a 100644 --- a/src/main/java/org/telegram/telegrambots/api/objects/inlinequery/result/InlineQueryResultGif.java +++ b/src/main/java/org/telegram/telegrambots/api/objects/inlinequery/result/InlineQueryResultGif.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; + import org.json.JSONObject; import org.telegram.telegrambots.api.objects.inlinequery.inputmessagecontent.InputMessageContent; import org.telegram.telegrambots.api.objects.replykeyboard.InlineKeyboardMarkup; @@ -51,7 +52,7 @@ public class InlineQueryResultGif implements InlineQueryResult { @JsonProperty(REPLY_MARKUP_FIELD) private InlineKeyboardMarkup replyMarkup; ///< Optional. Inline keyboard attached to the message - public String getType() { + public static String getType() { return type; } @@ -139,7 +140,7 @@ public class InlineQueryResultGif implements InlineQueryResult { @Override public JSONObject toJson() { JSONObject jsonObject = new JSONObject(); - jsonObject.put(TYPE_FIELD, this.type); + jsonObject.put(TYPE_FIELD, type); jsonObject.put(ID_FIELD, this.id); jsonObject.put(GIFURL_FIELD, this.gifUrl); if (gifWidth != null) { diff --git a/src/main/java/org/telegram/telegrambots/api/objects/inlinequery/result/InlineQueryResultMpeg4Gif.java b/src/main/java/org/telegram/telegrambots/api/objects/inlinequery/result/InlineQueryResultMpeg4Gif.java index ae5e2f03..6185db31 100644 --- a/src/main/java/org/telegram/telegrambots/api/objects/inlinequery/result/InlineQueryResultMpeg4Gif.java +++ b/src/main/java/org/telegram/telegrambots/api/objects/inlinequery/result/InlineQueryResultMpeg4Gif.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; + import org.json.JSONObject; import org.telegram.telegrambots.api.objects.inlinequery.inputmessagecontent.InputMessageContent; import org.telegram.telegrambots.api.objects.replykeyboard.InlineKeyboardMarkup; @@ -51,7 +52,7 @@ public class InlineQueryResultMpeg4Gif implements InlineQueryResult { @JsonProperty(REPLY_MARKUP_FIELD) private InlineKeyboardMarkup replyMarkup; ///< Optional. Inline keyboard attached to the message - public String getType() { + public static String getType() { return type; } diff --git a/src/main/java/org/telegram/telegrambots/bots/AbsSender.java b/src/main/java/org/telegram/telegrambots/bots/AbsSender.java index ae987e06..703bc816 100644 --- a/src/main/java/org/telegram/telegrambots/bots/AbsSender.java +++ b/src/main/java/org/telegram/telegrambots/bots/AbsSender.java @@ -2,6 +2,7 @@ package org.telegram.telegrambots.bots; import org.apache.http.HttpEntity; import org.apache.http.NameValuePair; +import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; @@ -12,7 +13,6 @@ import org.apache.http.entity.StringEntity; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import org.json.JSONObject; @@ -25,7 +25,12 @@ import org.telegram.telegrambots.api.methods.ForwardMessage; import org.telegram.telegrambots.api.methods.GetFile; import org.telegram.telegrambots.api.methods.GetMe; import org.telegram.telegrambots.api.methods.GetUserProfilePhotos; +import org.telegram.telegrambots.api.methods.groupadministration.GetChat; +import org.telegram.telegrambots.api.methods.groupadministration.GetChatAdministrators; +import org.telegram.telegrambots.api.methods.groupadministration.GetChatMember; +import org.telegram.telegrambots.api.methods.groupadministration.GetChatMemberCount; import org.telegram.telegrambots.api.methods.groupadministration.KickChatMember; +import org.telegram.telegrambots.api.methods.groupadministration.LeaveChat; import org.telegram.telegrambots.api.methods.groupadministration.UnbanChatMember; import org.telegram.telegrambots.api.methods.send.SendAudio; import org.telegram.telegrambots.api.methods.send.SendChatAction; @@ -41,6 +46,8 @@ import org.telegram.telegrambots.api.methods.send.SendVoice; import org.telegram.telegrambots.api.methods.updatingmessages.EditMessageCaption; import org.telegram.telegrambots.api.methods.updatingmessages.EditMessageReplyMarkup; import org.telegram.telegrambots.api.methods.updatingmessages.EditMessageText; +import org.telegram.telegrambots.api.objects.Chat; +import org.telegram.telegrambots.api.objects.ChatMember; import org.telegram.telegrambots.api.objects.File; import org.telegram.telegrambots.api.objects.Message; import org.telegram.telegrambots.api.objects.User; @@ -54,6 +61,10 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import static org.telegram.telegrambots.Constants.ERRORCODEFIELD; +import static org.telegram.telegrambots.Constants.ERRORDESCRIPTIONFIELD; /** * @author Ruben Bermudez @@ -61,8 +72,24 @@ import java.util.concurrent.Executors; * @brief Implementation of all the methods needed to interact with Telegram Servers * @date 14 of January of 2016 */ +@SuppressWarnings("unused") public abstract class AbsSender { private final ExecutorService exe = Executors.newSingleThreadExecutor(); + private volatile CloseableHttpClient httpclient; + private volatile RequestConfig requestConfig; + private static final int SOCKET_TIMEOUT = 75 * 1000; + + public AbsSender() { + httpclient = HttpClientBuilder.create() + .setSSLHostnameVerifier(new NoopHostnameVerifier()) + .setConnectionTimeToLive(70, TimeUnit.SECONDS) + .setMaxConnTotal(100) + .build(); + requestConfig = RequestConfig.copy(RequestConfig.custom().build()) + .setSocketTimeout(SOCKET_TIMEOUT) + .setConnectTimeout(SOCKET_TIMEOUT) + .setConnectionRequestTimeout(SOCKET_TIMEOUT).build(); + } /** * Returns the token of the bot to be able to perform Telegram Api Requests @@ -142,6 +169,41 @@ public abstract class AbsSender { return (Boolean) sendApiMethod(unbanChatMember); } + public Boolean leaveChat(LeaveChat leaveChat) throws TelegramApiException { + if (leaveChat == null) { + throw new TelegramApiException("Parameter leaveChat can not be null"); + } + return (Boolean) sendApiMethod(leaveChat); + } + + public Chat getChat(GetChat getChat) throws TelegramApiException { + if (getChat == null) { + throw new TelegramApiException("Parameter getChat can not be null"); + } + return (Chat) sendApiMethod(getChat); + } + + public List getChatAdministrators(GetChatAdministrators getChatAdministrators) throws TelegramApiException { + if (getChatAdministrators == null) { + throw new TelegramApiException("Parameter getChatAdministrators can not be null"); + } + return (ArrayList) sendApiMethod(getChatAdministrators); + } + + public ChatMember getChatMember(GetChatMember getChatMember) throws TelegramApiException { + if (getChatMember == null) { + throw new TelegramApiException("Parameter getChatMember can not be null"); + } + return (ChatMember) sendApiMethod(getChatMember); + } + + public Integer getChatMemberCount(GetChatMemberCount getChatMemberCount) throws TelegramApiException { + if (getChatMemberCount == null) { + throw new TelegramApiException("Parameter getChatMemberCount can not be null"); + } + return (Integer) sendApiMethod(getChatMemberCount); + } + public Message editMessageText(EditMessageText editMessageText) throws TelegramApiException { if (editMessageText == null) { throw new TelegramApiException("Parameter editMessageText can not be null"); @@ -179,12 +241,12 @@ public abstract class AbsSender { } public File getFile(GetFile getFile) throws TelegramApiException{ - if(getFile == null){ - throw new TelegramApiException("Parameter getFile can not be null"); - } - else if(getFile.getFileId() == null){ - throw new TelegramApiException("Attribute file_id in parameter getFile can not be null"); - } + if(getFile == null){ + throw new TelegramApiException("Parameter getFile can not be null"); + } + else if(getFile.getFileId() == null){ + throw new TelegramApiException("Attribute file_id in parameter getFile can not be null"); + } return (File) sendApiMethod(getFile); } @@ -244,7 +306,7 @@ public abstract class AbsSender { sendApiMethodAsync(forwardMessage, sentCallback); } - public void sendLocationAsync(SendLocation sendLocation, SentCallback sentCallback) throws TelegramApiException { + public void sendLocationAsync(SendLocation sendLocation, SentCallback sentCallback) throws TelegramApiException { if (sendLocation == null) { throw new TelegramApiException("Parameter sendLocation can not be null"); } @@ -301,6 +363,58 @@ public abstract class AbsSender { sendApiMethodAsync(unbanChatMember, sentCallback); } + public void leaveChatAsync(LeaveChat leaveChat, SentCallback sentCallback) throws TelegramApiException { + if (leaveChat == null) { + throw new TelegramApiException("Parameter leaveChat can not be null"); + } + if (sentCallback == null) { + throw new TelegramApiException("Parameter sentCallback can not be null"); + } + sendApiMethodAsync(leaveChat, sentCallback); + } + + public void getChatAsync(GetChat getChat, SentCallback sentCallback) throws TelegramApiException { + if (getChat == null) { + throw new TelegramApiException("Parameter getChat can not be null"); + } + if (sentCallback == null) { + throw new TelegramApiException("Parameter sentCallback can not be null"); + } + sendApiMethodAsync(getChat, sentCallback); + } + + public void getChatAdministratorsAsync(GetChatAdministrators getChatAdministrators, SentCallback> sentCallback) throws TelegramApiException { + if (getChatAdministrators == null) { + throw new TelegramApiException("Parameter getChatAdministrators can not be null"); + } + if (sentCallback == null) { + throw new TelegramApiException("Parameter sentCallback can not be null"); + } + sendApiMethodAsync(getChatAdministrators, sentCallback); + } + + public void getChatMemberAsync(GetChatMember getChatMember, SentCallback sentCallback) throws TelegramApiException { + if (getChatMember == null) { + throw new TelegramApiException("Parameter getChatMember can not be null"); + } + if (sentCallback == null) { + throw new TelegramApiException("Parameter sentCallback can not be null"); + } + sendApiMethodAsync(getChatMember, sentCallback); + } + + public void getChatMemberCountAsync(GetChatMemberCount getChatMemberCount, SentCallback sentCallback) throws TelegramApiException { + if (getChatMemberCount == null) { + throw new TelegramApiException("Parameter getChatMemberCount can not be null"); + } + if (sentCallback == null) { + throw new TelegramApiException("Parameter sentCallback can not be null"); + } + + sendApiMethodAsync(getChatMemberCount, sentCallback); + } + + public void editMessageTextAsync(EditMessageText editMessageText, SentCallback sentCallback) throws TelegramApiException { if (editMessageText == null) { throw new TelegramApiException("Parameter editMessageText can not be null"); @@ -382,9 +496,9 @@ public abstract class AbsSender { String responseContent; try { - CloseableHttpClient httpClient = HttpClients.createDefault(); String url = getBaseUrl() + SendDocument.PATH; HttpPost httppost = new HttpPost(url); + httppost.setConfig(requestConfig); if (sendDocument.isNewDocument()) { MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.addTextBody(SendDocument.CHATID_FIELD, sendDocument.getChatId()); @@ -396,7 +510,7 @@ public abstract class AbsSender { builder.addTextBody(SendDocument.REPLYTOMESSAGEID_FIELD, sendDocument.getReplayToMessageId().toString()); } if (sendDocument.getCaption() != null) { - builder.addTextBody(SendDocument.CAPTION_FIELD, sendDocument.getCaption()); + builder.addTextBody(SendDocument.CAPTION_FIELD, sendDocument.getCaption(), ContentType.create("text/plain", StandardCharsets.UTF_8)); } if (sendDocument.getDisableNotification() != null) { builder.addTextBody(SendDocument.DISABLENOTIFICATION_FIELD, sendDocument.getDisableNotification().toString()); @@ -408,7 +522,7 @@ public abstract class AbsSender { nameValuePairs.add(new BasicNameValuePair(SendDocument.CHATID_FIELD, sendDocument.getChatId())); nameValuePairs.add(new BasicNameValuePair(SendDocument.DOCUMENT_FIELD, sendDocument.getDocument())); if (sendDocument.getReplayMarkup() != null) { - nameValuePairs.add(new BasicNameValuePair(SendDocument.REPLYMARKUP_FIELD, sendDocument.getReplayMarkup().toString())); + nameValuePairs.add(new BasicNameValuePair(SendDocument.REPLYMARKUP_FIELD, sendDocument.getReplayMarkup().toJson().toString())); } if (sendDocument.getReplayToMessageId() != null) { nameValuePairs.add(new BasicNameValuePair(SendDocument.REPLYTOMESSAGEID_FIELD, sendDocument.getReplayToMessageId().toString())); @@ -422,17 +536,18 @@ public abstract class AbsSender { httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs, StandardCharsets.UTF_8)); } - CloseableHttpResponse response = httpClient.execute(httppost); - HttpEntity ht = response.getEntity(); - BufferedHttpEntity buf = new BufferedHttpEntity(ht); - responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); + try (CloseableHttpResponse response = httpclient.execute(httppost)) { + HttpEntity ht = response.getEntity(); + BufferedHttpEntity buf = new BufferedHttpEntity(ht); + responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); + } } catch (IOException e) { throw new TelegramApiException("Unable to send document", e); } JSONObject jsonObject = new JSONObject(responseContent); if (!jsonObject.getBoolean(Constants.RESPONSEFIELDOK)) { - throw new TelegramApiException("Error at sendDocument", jsonObject.getString("description")); + throw new TelegramApiException("Error at sendDocument", jsonObject.getString(ERRORDESCRIPTIONFIELD), jsonObject.getInt(ERRORCODEFIELD)); } return new Message(jsonObject.getJSONObject(Constants.RESPONSEFIELDRESULT)); @@ -441,9 +556,9 @@ public abstract class AbsSender { public Message sendPhoto(SendPhoto sendPhoto) throws TelegramApiException { String responseContent; try { - CloseableHttpClient httpClient = HttpClients.createDefault(); String url = getBaseUrl() + SendPhoto.PATH; HttpPost httppost = new HttpPost(url); + httppost.setConfig(requestConfig); if (sendPhoto.isNewPhoto()) { MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.addTextBody(SendPhoto.CHATID_FIELD, sendPhoto.getChatId()); @@ -455,7 +570,7 @@ public abstract class AbsSender { builder.addTextBody(SendPhoto.REPLYTOMESSAGEID_FIELD, sendPhoto.getReplayToMessageId().toString()); } if (sendPhoto.getCaption() != null) { - builder.addTextBody(SendPhoto.CAPTION_FIELD, sendPhoto.getCaption()); + builder.addTextBody(SendPhoto.CAPTION_FIELD, sendPhoto.getCaption(), ContentType.create("text/plain", StandardCharsets.UTF_8)); } if (sendPhoto.getDisableNotification() != null) { builder.addTextBody(SendPhoto.DISABLENOTIFICATION_FIELD, sendPhoto.getDisableNotification().toString()); @@ -467,7 +582,7 @@ public abstract class AbsSender { nameValuePairs.add(new BasicNameValuePair(SendPhoto.CHATID_FIELD, sendPhoto.getChatId())); nameValuePairs.add(new BasicNameValuePair(SendPhoto.PHOTO_FIELD, sendPhoto.getPhoto())); if (sendPhoto.getReplayMarkup() != null) { - nameValuePairs.add(new BasicNameValuePair(SendPhoto.REPLYMARKUP_FIELD, sendPhoto.getReplayMarkup().toString())); + nameValuePairs.add(new BasicNameValuePair(SendPhoto.REPLYMARKUP_FIELD, sendPhoto.getReplayMarkup().toJson().toString())); } if (sendPhoto.getReplayToMessageId() != null) { nameValuePairs.add(new BasicNameValuePair(SendPhoto.REPLYTOMESSAGEID_FIELD, sendPhoto.getReplayToMessageId().toString())); @@ -481,17 +596,18 @@ public abstract class AbsSender { httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs, StandardCharsets.UTF_8)); } - CloseableHttpResponse response = httpClient.execute(httppost); - HttpEntity ht = response.getEntity(); - BufferedHttpEntity buf = new BufferedHttpEntity(ht); - responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); + try (CloseableHttpResponse response = httpclient.execute(httppost)) { + HttpEntity ht = response.getEntity(); + BufferedHttpEntity buf = new BufferedHttpEntity(ht); + responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); + } } catch (IOException e) { throw new TelegramApiException("Unable to send photo", e); } JSONObject jsonObject = new JSONObject(responseContent); if (!jsonObject.getBoolean(Constants.RESPONSEFIELDOK)) { - throw new TelegramApiException("Error at sendPhoto", jsonObject.getString("description")); + throw new TelegramApiException("Error at sendPhoto", jsonObject.getString(ERRORDESCRIPTIONFIELD), jsonObject.getInt(ERRORCODEFIELD)); } return new Message(jsonObject.getJSONObject(Constants.RESPONSEFIELDRESULT)); @@ -500,9 +616,9 @@ public abstract class AbsSender { public Message sendVideo(SendVideo sendVideo) throws TelegramApiException { String responseContent; try { - CloseableHttpClient httpClient = HttpClients.createDefault(); String url = getBaseUrl() + SendVideo.PATH; HttpPost httppost = new HttpPost(url); + httppost.setConfig(requestConfig); if (sendVideo.isNewVideo()) { MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.addTextBody(SendVideo.CHATID_FIELD, sendVideo.getChatId()); @@ -514,7 +630,7 @@ public abstract class AbsSender { builder.addTextBody(SendVideo.REPLYTOMESSAGEID_FIELD, sendVideo.getReplayToMessageId().toString()); } if (sendVideo.getCaption() != null) { - builder.addTextBody(SendVideo.CAPTION_FIELD, sendVideo.getCaption()); + builder.addTextBody(SendVideo.CAPTION_FIELD, sendVideo.getCaption(), ContentType.create("text/plain", StandardCharsets.UTF_8)); } if (sendVideo.getDuration() != null) { builder.addTextBody(SendVideo.DURATION_FIELD, sendVideo.getDuration().toString()); @@ -535,7 +651,7 @@ public abstract class AbsSender { nameValuePairs.add(new BasicNameValuePair(SendVideo.CHATID_FIELD, sendVideo.getChatId())); nameValuePairs.add(new BasicNameValuePair(SendVideo.VIDEO_FIELD, sendVideo.getVideo())); if (sendVideo.getReplayMarkup() != null) { - nameValuePairs.add(new BasicNameValuePair(SendVideo.REPLYMARKUP_FIELD, sendVideo.getReplayMarkup().toString())); + nameValuePairs.add(new BasicNameValuePair(SendVideo.REPLYMARKUP_FIELD, sendVideo.getReplayMarkup().toJson().toString())); } if (sendVideo.getReplayToMessageId() != null) { nameValuePairs.add(new BasicNameValuePair(SendVideo.REPLYTOMESSAGEID_FIELD, sendVideo.getReplayToMessageId().toString())); @@ -558,17 +674,18 @@ public abstract class AbsSender { httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs, StandardCharsets.UTF_8)); } - CloseableHttpResponse response = httpClient.execute(httppost); - HttpEntity ht = response.getEntity(); - BufferedHttpEntity buf = new BufferedHttpEntity(ht); - responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); + try (CloseableHttpResponse response = httpclient.execute(httppost)) { + HttpEntity ht = response.getEntity(); + BufferedHttpEntity buf = new BufferedHttpEntity(ht); + responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); + } } catch (IOException e) { throw new TelegramApiException("Unable to send video", e); } JSONObject jsonObject = new JSONObject(responseContent); if (!jsonObject.getBoolean(Constants.RESPONSEFIELDOK)) { - throw new TelegramApiException("Error at sendVideo", jsonObject.getString("description")); + throw new TelegramApiException("Error at sendVideo", jsonObject.getString(ERRORDESCRIPTIONFIELD), jsonObject.getInt(ERRORCODEFIELD)); } return new Message(jsonObject.getJSONObject(Constants.RESPONSEFIELDRESULT)); @@ -578,9 +695,9 @@ public abstract class AbsSender { String responseContent; try { - CloseableHttpClient httpClient = HttpClients.createDefault(); String url = getBaseUrl() + SendSticker.PATH; HttpPost httppost = new HttpPost(url); + httppost.setConfig(requestConfig); if (sendSticker.isNewSticker()) { MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.addTextBody(SendSticker.CHATID_FIELD, sendSticker.getChatId()); @@ -601,7 +718,7 @@ public abstract class AbsSender { nameValuePairs.add(new BasicNameValuePair(SendSticker.CHATID_FIELD, sendSticker.getChatId())); nameValuePairs.add(new BasicNameValuePair(SendSticker.STICKER_FIELD, sendSticker.getSticker())); if (sendSticker.getReplayMarkup() != null) { - nameValuePairs.add(new BasicNameValuePair(SendSticker.REPLYMARKUP_FIELD, sendSticker.getReplayMarkup().toString())); + nameValuePairs.add(new BasicNameValuePair(SendSticker.REPLYMARKUP_FIELD, sendSticker.getReplayMarkup().toJson().toString())); } if (sendSticker.getReplayToMessageId() != null) { nameValuePairs.add(new BasicNameValuePair(SendSticker.REPLYTOMESSAGEID_FIELD, sendSticker.getReplayToMessageId().toString())); @@ -612,17 +729,18 @@ public abstract class AbsSender { httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs, StandardCharsets.UTF_8)); } - CloseableHttpResponse response = httpClient.execute(httppost); - HttpEntity ht = response.getEntity(); - BufferedHttpEntity buf = new BufferedHttpEntity(ht); - responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); + try (CloseableHttpResponse response = httpclient.execute(httppost)) { + HttpEntity ht = response.getEntity(); + BufferedHttpEntity buf = new BufferedHttpEntity(ht); + responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); + } } catch (IOException e) { throw new TelegramApiException("Unable to send sticker", e); } JSONObject jsonObject = new JSONObject(responseContent); if (!jsonObject.getBoolean(Constants.RESPONSEFIELDOK)) { - throw new TelegramApiException("Error at sendSticker", jsonObject.getString("description")); + throw new TelegramApiException("Error at sendSticker", jsonObject.getString(ERRORDESCRIPTIONFIELD), jsonObject.getInt(ERRORCODEFIELD)); } return new Message(jsonObject.getJSONObject(Constants.RESPONSEFIELDRESULT)); @@ -637,12 +755,11 @@ public abstract class AbsSender { public Message sendAudio(SendAudio sendAudio) throws TelegramApiException { String responseContent; - + try { - CloseableHttpClient httpClient = HttpClients.createDefault(); String url = getBaseUrl() + SendAudio.PATH; HttpPost httppost = new HttpPost(url); - + httppost.setConfig(requestConfig); if (sendAudio.isNewAudio()) { MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.addTextBody(SendAudio.CHATID_FIELD, sendAudio.getChatId()); @@ -660,7 +777,7 @@ public abstract class AbsSender { builder.addTextBody(SendAudio.TITLE_FIELD, sendAudio.getTitle()); } if(sendAudio.getDuration() != null){ - builder.addTextBody(SendAudio.DURATION_FIELD, sendAudio.getDuration().toString()); + builder.addTextBody(SendAudio.DURATION_FIELD, sendAudio.getDuration().toString()); } if (sendAudio.getDisableNotification() != null) { builder.addTextBody(SendAudio.DISABLENOTIFICATION_FIELD, sendAudio.getDisableNotification().toString()); @@ -672,7 +789,7 @@ public abstract class AbsSender { nameValuePairs.add(new BasicNameValuePair(SendAudio.CHATID_FIELD, sendAudio.getChatId())); nameValuePairs.add(new BasicNameValuePair(SendAudio.AUDIO_FIELD, sendAudio.getAudio())); if (sendAudio.getReplayMarkup() != null) { - nameValuePairs.add(new BasicNameValuePair(SendAudio.REPLYMARKUP_FIELD, sendAudio.getReplayMarkup().toString())); + nameValuePairs.add(new BasicNameValuePair(SendAudio.REPLYMARKUP_FIELD, sendAudio.getReplayMarkup().toJson().toString())); } if (sendAudio.getReplayToMessageId() != null) { nameValuePairs.add(new BasicNameValuePair(SendAudio.REPLYTOMESSAGEID_FIELD, sendAudio.getReplayToMessageId().toString())); @@ -689,10 +806,11 @@ public abstract class AbsSender { httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs, StandardCharsets.UTF_8)); } - CloseableHttpResponse response = httpClient.execute(httppost); - HttpEntity ht = response.getEntity(); - BufferedHttpEntity buf = new BufferedHttpEntity(ht); - responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); + try (CloseableHttpResponse response = httpclient.execute(httppost)) { + HttpEntity ht = response.getEntity(); + BufferedHttpEntity buf = new BufferedHttpEntity(ht); + responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); + } } catch (IOException e) { throw new TelegramApiException("Unable to send sticker", e); } @@ -704,10 +822,10 @@ public abstract class AbsSender { * {"description":"[Error]: Bad Request: chat not found","error_code":400,"ok":false} */ if (!jsonObject.getBoolean(Constants.RESPONSEFIELDOK)) { - throw new TelegramApiException("Error at sendAudio", jsonObject.getString("description")); + throw new TelegramApiException("Error at sendAudio", jsonObject.getString(ERRORDESCRIPTIONFIELD), jsonObject.getInt(ERRORCODEFIELD)); } - - // and if not, we can expect a "result" section. and out of this can a new Message object be built + + // and if not, we can expect a "result" section. and out of this can a new Message object be built return new Message(jsonObject.getJSONObject(Constants.RESPONSEFIELDRESULT)); } @@ -721,10 +839,9 @@ public abstract class AbsSender { String responseContent; try { - CloseableHttpClient httpClient = HttpClients.createDefault(); String url = getBaseUrl() + SendVoice.PATH; HttpPost httppost = new HttpPost(url); - + httppost.setConfig(requestConfig); if (sendVoice.isNewVoice()) { MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.addTextBody(SendVoice.CHATID_FIELD, sendVoice.getChatId()); @@ -748,7 +865,7 @@ public abstract class AbsSender { nameValuePairs.add(new BasicNameValuePair(SendVoice.CHATID_FIELD, sendVoice.getChatId())); nameValuePairs.add(new BasicNameValuePair(SendVoice.AUDIO_FIELD, sendVoice.getAudio())); if (sendVoice.getReplayMarkup() != null) { - nameValuePairs.add(new BasicNameValuePair(SendVoice.REPLYMARKUP_FIELD, sendVoice.getReplayMarkup().toString())); + nameValuePairs.add(new BasicNameValuePair(SendVoice.REPLYMARKUP_FIELD, sendVoice.getReplayMarkup().toJson().toString())); } if (sendVoice.getReplayToMessageId() != null) { nameValuePairs.add(new BasicNameValuePair(SendVoice.REPLYTOMESSAGEID_FIELD, sendVoice.getReplayToMessageId().toString())); @@ -762,17 +879,18 @@ public abstract class AbsSender { httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs, StandardCharsets.UTF_8)); } - CloseableHttpResponse response = httpClient.execute(httppost); - HttpEntity ht = response.getEntity(); - BufferedHttpEntity buf = new BufferedHttpEntity(ht); - responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); + try (CloseableHttpResponse response = httpclient.execute(httppost)) { + HttpEntity ht = response.getEntity(); + BufferedHttpEntity buf = new BufferedHttpEntity(ht); + responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); + } } catch (IOException e) { throw new TelegramApiException("Unable to send sticker", e); } JSONObject jsonObject = new JSONObject(responseContent); if (!jsonObject.getBoolean(Constants.RESPONSEFIELDOK)) { - throw new TelegramApiException("Error at sendVoice", jsonObject.getString("description")); + throw new TelegramApiException("Error at sendVoice", jsonObject.getString(ERRORDESCRIPTIONFIELD), jsonObject.getInt(ERRORCODEFIELD)); } return new Message(jsonObject.getJSONObject(Constants.RESPONSEFIELDRESULT)); @@ -780,26 +898,28 @@ public abstract class AbsSender { // Simplified methods - private void sendApiMethodAsync(BotApiMethod method, SentCallback callback) { + private , Callback extends SentCallback> void sendApiMethodAsync(Method method, Callback callback) { + //noinspection Convert2Lambda exe.submit(new Runnable() { @Override public void run() { try { - CloseableHttpClient httpclient = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build(); String url = getBaseUrl() + method.getPath(); HttpPost httppost = new HttpPost(url); + httppost.setConfig(requestConfig); httppost.addHeader("charset", StandardCharsets.UTF_8.name()); httppost.setEntity(new StringEntity(method.toJson().toString(), ContentType.APPLICATION_JSON)); - CloseableHttpResponse response = httpclient.execute(httppost); - HttpEntity ht = response.getEntity(); - BufferedHttpEntity buf = new BufferedHttpEntity(ht); - String responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); + try (CloseableHttpResponse response = httpclient.execute(httppost)) { + HttpEntity ht = response.getEntity(); + BufferedHttpEntity buf = new BufferedHttpEntity(ht); + String responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); - JSONObject jsonObject = new JSONObject(responseContent); - if (!jsonObject.getBoolean(Constants.RESPONSEFIELDOK)) { - callback.onError(method, jsonObject); + JSONObject jsonObject = new JSONObject(responseContent); + if (!jsonObject.getBoolean(Constants.RESPONSEFIELDOK)) { + callback.onError(method, jsonObject); + } + callback.onResult(method, jsonObject); } - callback.onResult(method, jsonObject); } catch (IOException e) { callback.onException(method, e); } @@ -811,22 +931,23 @@ public abstract class AbsSender { private Serializable sendApiMethod(BotApiMethod method) throws TelegramApiException { String responseContent; try { - CloseableHttpClient httpclient = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build(); String url = getBaseUrl() + method.getPath(); HttpPost httppost = new HttpPost(url); + httppost.setConfig(requestConfig); httppost.addHeader("charset", StandardCharsets.UTF_8.name()); httppost.setEntity(new StringEntity(method.toJson().toString(), ContentType.APPLICATION_JSON)); - CloseableHttpResponse response = httpclient.execute(httppost); - HttpEntity ht = response.getEntity(); - BufferedHttpEntity buf = new BufferedHttpEntity(ht); - responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); + try (CloseableHttpResponse response = httpclient.execute(httppost)) { + HttpEntity ht = response.getEntity(); + BufferedHttpEntity buf = new BufferedHttpEntity(ht); + responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); + } } catch (IOException e) { throw new TelegramApiException("Unable to execute " + method.getPath() + " method", e); } JSONObject jsonObject = new JSONObject(responseContent); if (!jsonObject.getBoolean(Constants.RESPONSEFIELDOK)) { - throw new TelegramApiException("Error at " + method.getPath(), jsonObject.getString("description")); + throw new TelegramApiException("Error at " + method.getPath(), jsonObject.getString(ERRORDESCRIPTIONFIELD), jsonObject.getInt(ERRORCODEFIELD)); } return method.deserializeResponse(jsonObject); diff --git a/src/main/java/org/telegram/telegrambots/logging/BotLogger.java b/src/main/java/org/telegram/telegrambots/logging/BotLogger.java new file mode 100644 index 00000000..681c43bc --- /dev/null +++ b/src/main/java/org/telegram/telegrambots/logging/BotLogger.java @@ -0,0 +1,167 @@ +package org.telegram.telegrambots.logging; + +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * @author Ruben Bermudez + * @version 2.0 + * @brief Logger to file + * @date 21/01/15 + */ +public class BotLogger { + private static final Logger logger = Logger.getLogger("Telegram Bots Api"); + + public static void setLevel(Level level) { + logger.setLevel(level); + } + + public static void registerLogger(Handler handler) { + logger.addHandler(handler); + } + + public static void log(Level level, String tag, String msg) { + logger.log(level, String.format("%s - %s", tag, msg)); + } + + public static void severe(String tag, String msg) { + logger.severe(String.format("%s - %s", tag, msg)); + } + + public static void warn(String tag, String msg) { + warning(tag, msg); + } + + public static void debug(String tag, String msg) { + fine(tag, msg); + } + + public static void error(String tag, String msg) { + severe(tag, msg); + } + + public static void trace(String tag, String msg) { + finer(tag, msg); + } + + public static void warning(String tag, String msg) { + logger.warning(String.format("%s - %s", tag, msg)); + } + + public static void info(String tag, String msg) { + logger.info(String.format("%s - %s", tag, msg)); + } + + public static void config(String tag, String msg) { + logger.config(String.format("%s - %s", tag, msg)); + } + + public static void fine(String tag, String msg) { + logger.fine(String.format("%s - %s", tag, msg)); + } + + public static void finer(String tag, String msg) { + logger.finer(String.format("%s - %s", tag, msg)); + } + + public static void finest(String tag, String msg) { + logger.finest(String.format("%s - %s", tag, msg)); + } + + public static void log(Level level, String tag, Throwable throwable) { + logger.log(level, tag, throwable); + } + + public static void log(Level level, String tag, String msg, Throwable thrown) { + logger.log(level, String.format("%s - %s", tag, msg), thrown); + } + + public static void severe(String tag, Throwable throwable) { + logger.log(Level.SEVERE, tag, throwable); + } + + public static void warning(String tag, Throwable throwable) { + logger.log(Level.WARNING, tag, throwable); + } + + public static void info(String tag, Throwable throwable) { + logger.log(Level.INFO, tag, throwable); + } + + public static void config(String tag, Throwable throwable) { + logger.log(Level.CONFIG, tag, throwable); + } + + public static void fine(String tag, Throwable throwable) { + logger.log(Level.FINE, tag, throwable); + } + + public static void finer(String tag, Throwable throwable) { + logger.log(Level.FINER, tag, throwable); + } + + public static void finest(String tag, Throwable throwable) { + logger.log(Level.FINEST, tag, throwable); + } + + public static void warn(String tag, Throwable throwable) { + warning(tag, throwable); + } + + public static void debug(String tag, Throwable throwable) { + fine(tag, throwable); + } + + public static void error(String tag, Throwable throwable) { + severe(tag, throwable); + } + + public static void trace(String tag, Throwable throwable) { + finer(tag, throwable); + } + + public static void severe(String msg, String tag, Throwable throwable) { + log(Level.SEVERE, tag, msg, throwable); + } + + public static void warning(String msg, String tag, Throwable throwable) { + log(Level.WARNING, tag, msg, throwable); + } + + public static void info(String msg, String tag, Throwable throwable) { + log(Level.INFO, tag, msg, throwable); + } + + public static void config(String msg, String tag, Throwable throwable) { + log(Level.CONFIG, tag, msg, throwable); + } + + public static void fine(String msg, String tag, Throwable throwable) { + log(Level.FINE, tag, msg, throwable); + } + + public static void finer(String msg, String tag, Throwable throwable) { + log(Level.FINER, tag, msg, throwable); + } + + public static void finest(String msg, String tag, Throwable throwable) { + log(Level.FINEST, tag, msg, throwable); + } + + public static void warn(String msg, String tag, Throwable throwable) { + log(Level.WARNING, tag, msg, throwable); + } + + public static void debug(String msg, String tag, Throwable throwable) { + log(Level.FINE, tag, msg, throwable); + } + + public static void error(String msg, String tag, Throwable throwable) { + log(Level.SEVERE, tag, msg, throwable); + } + + public static void trace(String msg, String tag, Throwable throwable) { + log(Level.FINER, tag, msg, throwable); + } +} diff --git a/src/main/java/org/telegram/telegrambots/logging/BotsFileHandler.java b/src/main/java/org/telegram/telegrambots/logging/BotsFileHandler.java new file mode 100644 index 00000000..c225f497 --- /dev/null +++ b/src/main/java/org/telegram/telegrambots/logging/BotsFileHandler.java @@ -0,0 +1,45 @@ +package org.telegram.telegrambots.logging; + +import java.io.IOException; +import java.util.logging.FileHandler; + +/** + * @author Ruben Bermudez + * @version 1.0 + * @brief TODO + * @date 19 of May of 2016 + */ +public class BotsFileHandler extends FileHandler { + private static final String filePattern = "./TelegramBots%g.%u.log"; + + public BotsFileHandler() throws IOException, SecurityException { + super(filePattern, 1024 * 1024 * 10, 50, true); + setFormatter(new FileFormatter()); + } + + public BotsFileHandler(int limit, int count) throws IOException, SecurityException { + super(filePattern, limit, count); + setFormatter(new FileFormatter()); + } + + public BotsFileHandler(String pattern) throws IOException, SecurityException { + super(pattern); + setFormatter(new FileFormatter()); + } + + public BotsFileHandler(String pattern, boolean append) throws IOException, SecurityException { + super(pattern, append); + setFormatter(new FileFormatter()); + } + + public BotsFileHandler(String pattern, int limit, int count) throws IOException, SecurityException { + super(pattern, limit, count); + setFormatter(new FileFormatter()); + } + + public BotsFileHandler(String pattern, int limit, int count, boolean append) throws IOException, SecurityException { + super(pattern, limit, count, append); + setFormatter(new FileFormatter()); + } + +} diff --git a/src/main/java/org/telegram/telegrambots/logging/FileFormatter.java b/src/main/java/org/telegram/telegrambots/logging/FileFormatter.java new file mode 100644 index 00000000..a36da759 --- /dev/null +++ b/src/main/java/org/telegram/telegrambots/logging/FileFormatter.java @@ -0,0 +1,52 @@ +package org.telegram.telegrambots.logging; + +import java.time.LocalDateTime; +import java.util.logging.Formatter; +import java.util.logging.Level; +import java.util.logging.LogRecord; + +/** + * @author Ruben Bermudez + * @version 1.0 + * @brief TODO + * @date 19 of May of 2016 + */ +class FileFormatter extends Formatter { + + @Override + public String format(LogRecord record) { + final LocalDateTime currentDate = LocalDateTime.now(); + final String dateForLog = dateFormatterForLogs(currentDate); + String result; + if (record.getThrown() == null) { + result = logMsgToFile(record.getLevel(), record.getMessage(), dateForLog); + } else { + result = logThrowableToFile(record.getLevel(), record.getMessage(), record.getThrown(), dateForLog); + } + return result; + } + + private static String dateFormatterForLogs(LocalDateTime dateTime) { + String dateString = "["; + dateString += dateTime.getDayOfMonth() + "_"; + dateString += dateTime.getMonthValue() + "_"; + dateString += dateTime.getYear() + "_"; + dateString += dateTime.getHour() + ":"; + dateString += dateTime.getMinute() + ":"; + dateString += dateTime.getSecond(); + dateString += "] "; + return dateString; + } + + private static String logMsgToFile(Level level, String msg, String dateForLog) { + return String.format("%s{%s} %s\n", dateForLog, level.toString(), msg); + } + + private static String logThrowableToFile(Level level, String message, Throwable throwable, String dateForLog) { + String throwableLog = String.format("%s{%s} %s - %s\n", dateForLog, level.toString(), message, throwable.toString()); + for (StackTraceElement element : throwable.getStackTrace()) { + throwableLog += "\tat " + element + "\n"; + } + return throwableLog; + } +} diff --git a/src/main/java/org/telegram/telegrambots/updatesreceivers/BotSession.java b/src/main/java/org/telegram/telegrambots/updatesreceivers/BotSession.java index f770700c..39b5f1ec 100644 --- a/src/main/java/org/telegram/telegrambots/updatesreceivers/BotSession.java +++ b/src/main/java/org/telegram/telegrambots/updatesreceivers/BotSession.java @@ -1,8 +1,8 @@ package org.telegram.telegrambots.updatesreceivers; import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.entity.BufferedHttpEntity; @@ -14,8 +14,9 @@ import org.apache.http.util.EntityUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import org.telegram.telegrambots.BotLogger; +import org.telegram.telegrambots.logging.BotLogger; import org.telegram.telegrambots.Constants; +import org.telegram.telegrambots.TelegramApiException; import org.telegram.telegrambots.api.methods.updates.GetUpdates; import org.telegram.telegrambots.api.objects.Update; import org.telegram.telegrambots.bots.ITelegramLongPollingBot; @@ -26,6 +27,9 @@ import java.nio.charset.StandardCharsets; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.TimeUnit; +import static org.telegram.telegrambots.Constants.ERRORCODEFIELD; +import static org.telegram.telegrambots.Constants.ERRORDESCRIPTIONFIELD; + /** * @author Ruben Bermudez * @version 1.0 @@ -34,7 +38,7 @@ import java.util.concurrent.TimeUnit; */ public class BotSession { private static final String LOGTAG = "BOTSESSION"; - private static final int SOCKET_TIMEOUT = 30 * 1000; + private static final int SOCKET_TIMEOUT = 75 * 1000; private final ITelegramLongPollingBot callback; private final ReaderThread readerThread; @@ -44,11 +48,21 @@ public class BotSession { private int lastReceivedUpdate = 0; private volatile boolean running = true; private volatile CloseableHttpClient httpclient; + private volatile RequestConfig requestConfig; public BotSession(String token, ITelegramLongPollingBot callback) { this.token = token; this.callback = callback; + httpclient = HttpClientBuilder.create() + .setSSLHostnameVerifier(new NoopHostnameVerifier()) + .setConnectionTimeToLive(70, TimeUnit.SECONDS) + .setMaxConnTotal(100) + .build(); + requestConfig = RequestConfig.copy(RequestConfig.custom().build()) + .setSocketTimeout(SOCKET_TIMEOUT) + .setConnectTimeout(SOCKET_TIMEOUT) + .setConnectionRequestTimeout(SOCKET_TIMEOUT).build(); this.readerThread = new ReaderThread(); readerThread.setName(callback.getBotUsername() + " Telegram Connection"); this.readerThread.start(); @@ -79,35 +93,25 @@ public class BotSession { public void run() { setPriority(Thread.MIN_PRIORITY); while(running) { - GetUpdates request = new GetUpdates(); - request.setLimit(100); - request.setTimeout(20); - request.setOffset(lastReceivedUpdate + 1); - httpclient = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).setConnectionTimeToLive(20, TimeUnit.SECONDS).build(); - String url = Constants.BASEURL + token + "/" + GetUpdates.PATH; - //config - RequestConfig defaultRequestConfig = RequestConfig.custom().build(); - RequestConfig requestConfig = RequestConfig.copy(defaultRequestConfig) - .setSocketTimeout(SOCKET_TIMEOUT) - .setConnectTimeout(SOCKET_TIMEOUT) - .setConnectionRequestTimeout(SOCKET_TIMEOUT).build(); - //http client - HttpPost httpPost = new HttpPost(url); try { + GetUpdates request = new GetUpdates(); + request.setLimit(100); + request.setTimeout(50); + request.setOffset(lastReceivedUpdate + 1); + String url = Constants.BASEURL + token + "/" + GetUpdates.PATH; + //http client + HttpPost httpPost = new HttpPost(url); httpPost.addHeader("charset", StandardCharsets.UTF_8.name()); httpPost.setConfig(requestConfig); httpPost.setEntity(new StringEntity(request.toJson().toString(), ContentType.APPLICATION_JSON)); - HttpResponse response; - response = httpclient.execute(httpPost); - HttpEntity ht = response.getEntity(); - BufferedHttpEntity buf = new BufferedHttpEntity(ht); - String responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); - - try { + try (CloseableHttpResponse response = httpclient.execute(httpPost)) { + HttpEntity ht = response.getEntity(); + BufferedHttpEntity buf = new BufferedHttpEntity(ht); + String responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); JSONObject jsonObject = new JSONObject(responseContent); if (!jsonObject.getBoolean(Constants.RESPONSEFIELDOK)) { - throw new InvalidObjectException(jsonObject.toString()); + throw new TelegramApiException("Error getting updates", jsonObject.getString(ERRORDESCRIPTIONFIELD), jsonObject.getInt(ERRORCODEFIELD)); } JSONArray jsonArray = jsonObject.getJSONArray(Constants.RESPONSEFIELDRESULT); if (jsonArray.length() != 0) { @@ -130,7 +134,7 @@ public class BotSession { BotLogger.severe(LOGTAG, e); } } - } catch (InvalidObjectException | JSONException e) { + } catch (InvalidObjectException | JSONException | TelegramApiException e) { BotLogger.severe(LOGTAG, e); } } catch (Exception global) {