From 329c3c73ab829fdaca80acb64d17e6df3442e7c0 Mon Sep 17 00:00:00 2001 From: Gemini_13 Date: Mon, 1 Nov 2021 01:04:10 +0200 Subject: [PATCH 1/8] disable_web_page_preview Added parameter "disable_web_page_preview" --- src/UniversalTelegramBot.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/UniversalTelegramBot.h b/src/UniversalTelegramBot.h index 5fc97ee..f535a73 100644 --- a/src/UniversalTelegramBot.h +++ b/src/UniversalTelegramBot.h @@ -85,7 +85,8 @@ class UniversalTelegramBot { bool getMe(); bool sendSimpleMessage(const String& chat_id, const String& text, const String& parse_mode); - bool sendMessage(const String& chat_id, const String& text, const String& parse_mode = "", int message_id = 0); + bool sendMessage(const String& chat_id, const String& text, const String& parse_mode = "", int message_id = 0, + bool disable_web_page_preview = false); bool sendMessageWithReplyKeyboard(const String& chat_id, const String& text, const String& parse_mode, const String& keyboard, bool resize = false, bool oneTime = false, From e12c0dd7adee25ae20f59aec68e94c18a622e46d Mon Sep 17 00:00:00 2001 From: Gemini_13 Date: Mon, 1 Nov 2021 01:07:09 +0200 Subject: [PATCH 2/8] disable_web_page_preview Added parameter "disable_web_page_preview" --- src/UniversalTelegramBot.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/UniversalTelegramBot.cpp b/src/UniversalTelegramBot.cpp index fbb1ac7..6ecfd2b 100644 --- a/src/UniversalTelegramBot.cpp +++ b/src/UniversalTelegramBot.cpp @@ -560,7 +560,7 @@ bool UniversalTelegramBot::sendSimpleMessage(const String& chat_id, const String } bool UniversalTelegramBot::sendMessage(const String& chat_id, const String& text, - const String& parse_mode, int message_id) { // added message_id + const String& parse_mode, int message_id, bool disable_web_page_preview) { // added message_id DynamicJsonDocument payload(maxMessageLength); payload["chat_id"] = chat_id; From abd6d9760fcc1ba76b60db33333a90fdef9a985a Mon Sep 17 00:00:00 2001 From: Gemini_13 Date: Wed, 3 Nov 2021 01:33:39 +0200 Subject: [PATCH 3/8] Added function deleteMessage(), maxMessageLength and fixes for disable_web_page_preview and debug --- src/UniversalTelegramBot.cpp | 55 ++++++++++++++++++++++++++++++------ src/UniversalTelegramBot.h | 9 +++--- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/src/UniversalTelegramBot.cpp b/src/UniversalTelegramBot.cpp index 6ecfd2b..3352cef 100644 --- a/src/UniversalTelegramBot.cpp +++ b/src/UniversalTelegramBot.cpp @@ -38,9 +38,10 @@ #define ZERO_COPY(STR) ((char*)STR.c_str()) #define BOT_CMD(STR) buildCommand(F(STR)) -UniversalTelegramBot::UniversalTelegramBot(const String& token, Client &client) { +UniversalTelegramBot::UniversalTelegramBot(const String& token, Client &client, int maxMessageLength) { updateToken(token); this->client = &client; + this->maxMessageLength = maxMessageLength; } void UniversalTelegramBot::updateToken(const String& token) { @@ -328,15 +329,15 @@ bool UniversalTelegramBot::setMyCommands(const String& commandArray) { payload["commands"] = serialized(commandArray); bool sent = false; String response = ""; - #if defined(_debug) - Serial.println(F("sendSetMyCommands: SEND Post /setMyCommands")); - #endif // defined(_debug) + #ifdef TELEGRAM_DEBUG + Serial.println(F("sendSetMyCommands: SEND Post /setMyCommands")); + #endif unsigned long sttime = millis(); while (millis() - sttime < 8000ul) { // loop for a while to send the message response = sendPostToTelegram(BOT_CMD("setMyCommands"), payload.as()); - #ifdef _debug - Serial.println("setMyCommands response" + response); + #ifdef TELEGRAM_DEBUG + Serial.println("setMyCommands response" + response); #endif sent = checkForOkResponse(response); if (sent) break; @@ -560,7 +561,7 @@ bool UniversalTelegramBot::sendSimpleMessage(const String& chat_id, const String } bool UniversalTelegramBot::sendMessage(const String& chat_id, const String& text, - const String& parse_mode, int message_id, bool disable_web_page_preview) { // added message_id + const String& parse_mode, int message_id, bool disable_web_page_preview) { DynamicJsonDocument payload(maxMessageLength); payload["chat_id"] = chat_id; @@ -572,9 +573,47 @@ bool UniversalTelegramBot::sendMessage(const String& chat_id, const String& text if (parse_mode != "") payload["parse_mode"] = parse_mode; + if (disable_web_page_preview) + payload["disable_web_page_preview"] = disable_web_page_preview; + return sendPostMessage(payload.as(), message_id); // if message id == 0 then edit is false, else edit is true } +/*********************************************************************** + * DeleteMessage - function to delete message by message_id * + * Function description and limitations: * + * https://core.telegram.org/bots/api#deletemessage * + ***********************************************************************/ +bool UniversalTelegramBot::deleteMessage(const String& chat_id, int message_id) { + if (message_id == 0) + { + #ifdef TELEGRAM_DEBUG + Serial.println(F("deleteMessage: message_id not passed for deletion")); + #endif + return false; + } + + DynamicJsonDocument payload(maxMessageLength); + payload["chat_id"] = chat_id; + payload["message_id"] = message_id; + + #ifdef TELEGRAM_DEBUG + Serial.print(F("deleteMessage: SEND Post Message: ")); + serializeJson(payload, Serial); + Serial.println(); + #endif + + String response = sendPostToTelegram(BOT_CMD("deleteMessage"), payload.as()); + #ifdef TELEGRAM_DEBUG + Serial.print(F("deleteMessage response:")); + Serial.println(response); + #endif + + bool sent = checkForOkResponse(response); + closeClient(); + return sent; +} + bool UniversalTelegramBot::sendMessageWithReplyKeyboard( const String& chat_id, const String& text, const String& parse_mode, const String& keyboard, bool resize, bool oneTime, bool selective) { @@ -809,7 +848,7 @@ bool UniversalTelegramBot::answerCallbackQuery(const String &query_id, const Str if (url.length() > 0) payload["url"] = url; String response = sendPostToTelegram(BOT_CMD("answerCallbackQuery"), payload.as()); - #ifdef _debug + #ifdef TELEGRAM_DEBUG Serial.print(F("answerCallbackQuery response:")); Serial.println(response); #endif diff --git a/src/UniversalTelegramBot.h b/src/UniversalTelegramBot.h index f535a73..4932c5a 100644 --- a/src/UniversalTelegramBot.h +++ b/src/UniversalTelegramBot.h @@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef UniversalTelegramBot_h #define UniversalTelegramBot_h +//unmark following line to enable debug mode //#define TELEGRAM_DEBUG 1 #define ARDUINOJSON_DECODE_UNICODE 1 #define ARDUINOJSON_USE_LONG_LONG 1 @@ -34,9 +35,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define TELEGRAM_SSL_PORT 443 #define HANDLE_MESSAGES 1 -//unmark following line to enable debug mode -//#define _debug - typedef bool (*MoreDataAvailable)(); typedef byte (*GetNextByte)(); typedef byte* (*GetNextBuffer)(); @@ -67,7 +65,7 @@ struct telegramMessage { class UniversalTelegramBot { public: - UniversalTelegramBot(const String& token, Client &client); + UniversalTelegramBot(const String& token, Client &client, int maxMessageLength = 1500); void updateToken(const String& token); String getToken(); String sendGetToTelegram(const String& command); @@ -86,7 +84,8 @@ class UniversalTelegramBot { bool sendSimpleMessage(const String& chat_id, const String& text, const String& parse_mode); bool sendMessage(const String& chat_id, const String& text, const String& parse_mode = "", int message_id = 0, - bool disable_web_page_preview = false); + bool disable_web_page_preview = false); + bool deleteMessage(const String& chat_id, int message_id = 0); bool sendMessageWithReplyKeyboard(const String& chat_id, const String& text, const String& parse_mode, const String& keyboard, bool resize = false, bool oneTime = false, From 7f5726a355e1b0276011421d6e83bda8e9c6b9f4 Mon Sep 17 00:00:00 2001 From: Gemini_13 Date: Wed, 3 Nov 2021 01:34:45 +0200 Subject: [PATCH 4/8] Example for deleteMessage() and sendMessageWithInlineKeyboard() --- .../DeleteMessage/InlineKeyboardMarkup.ino | 178 ++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 examples/ESP8266/DeleteMessage/InlineKeyboardMarkup.ino diff --git a/examples/ESP8266/DeleteMessage/InlineKeyboardMarkup.ino b/examples/ESP8266/DeleteMessage/InlineKeyboardMarkup.ino new file mode 100644 index 0000000..dbb92a1 --- /dev/null +++ b/examples/ESP8266/DeleteMessage/InlineKeyboardMarkup.ino @@ -0,0 +1,178 @@ +#include +#include +#include + +// Wifi network station credentials +#define WIFI_SSID "YOUR_SSID" +#define WIFI_PASSWORD "YOUR_PASSWORD" +// Telegram BOT Token (Get from Botfather) +#define BOT_TOKEN "XXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + +const unsigned long BOT_MTBS = 1000; // mean time between scan messages + +X509List cert(TELEGRAM_CERTIFICATE_ROOT); +WiFiClientSecure secured_client; +UniversalTelegramBot bot(BOT_TOKEN, secured_client, 2500); +unsigned long bot_lasttime; + +void setup() +{ + Serial.begin(115200); + + connectToWifi(); + synchronizeTime(); +} + +void loop() +{ + if (millis() - bot_lasttime > BOT_MTBS) + { + int numNewMessages = bot.getUpdates(bot.last_message_received + 1); + + while (numNewMessages) + { + Serial.println("got response"); + handleNewMessages(numNewMessages); + numNewMessages = bot.getUpdates(bot.last_message_received + 1); + } + + bot_lasttime = millis(); + } +} + +void handleNewMessages(int numNewMessages) +{ + for (int i = 0; i < numNewMessages; i++) + { + telegramMessage message = bot.messages[i]; + + Serial.println("Received: " + message.text); + + String text = message.text; + String from_name = message.from_name; + int message_id = getMessageId(message); + + if (from_name == "") + { + from_name = "Guest"; + } + + if (text == "/options") + { + // Memory pool for JSON object tree. + // + // Inside the brackets, 400 is the size of the pool in bytes. + // Don't forget to change this value to match your JSON document. + // Use https://arduinojson.org/assistant to compute the capacity. + StaticJsonDocument<400> keyboard; + + StaticJsonDocument<100> menuItem0; + menuItem0["text"] = "Some button"; + menuItem0["callback_data"] = "/custom_action"; + keyboard[0].add(menuItem0); + + StaticJsonDocument<100> menuItem1; + menuItem1["text"] = "Go to Google"; + menuItem1["url"] = "https://www.google.com"; + keyboard[1].add(menuItem1); + + StaticJsonDocument<100> menuItem2; + menuItem2["text"] = "Close"; + menuItem2["callback_data"] = "/cancel"; + keyboard[2].add(menuItem2); + + bot.sendMessageWithInlineKeyboard( + message.chat_id, + "Choose from one of the following options", + "", + getKeyboardJson(keyboard), + message_id + ); + } + else if (text == "/custom_action") + { + Serial.println( + message_id != 0 ? "The keyboard will be replaced with test text." : "Only test text will be displayed." + ); + + bot.sendMessage(message.chat_id, "Lorem Ipsum", "", message_id); + } + else if (text == "/cancel") + { + Serial.println( + message_id != 0 ? "Keyboard will be deleted." : "Action will be ignored." + ); + + bot.deleteMessage(message.chat_id, message_id); + } + else if (text == "/start") + { + String welcome = "Welcome to Universal Arduino Telegram Bot library, " + from_name + ".\n"; + welcome += "This is example of Inline Keyboard Markup and deletion of the previous message.\n\n"; + welcome += "/options : returns the inline keyboard\n"; + welcome += "/custom_action : returns test text\n"; + + bot.sendMessage(message.chat_id, welcome, ""); + } + } +} + +void connectToWifi() +{ + WiFi.mode(WIFI_STA); + WiFi.disconnect(); + delay(100); + + Serial.print("Connecting to Wifi SSID "); + Serial.print(WIFI_SSID); + Serial.print(" "); + + WiFi.begin(WIFI_SSID, WIFI_PASSWORD); + secured_client.setTrustAnchors(&cert); + + while (WiFi.status() != WL_CONNECTED) + { + Serial.print("."); + delay(1000); + } + Serial.println(); + + Serial.print("WiFi connected. IP address: "); + Serial.println(WiFi.localIP()); +} + +void synchronizeTime() +{ + configTime(0, 0, "pool.ntp.org"); + + Serial.print("Time synchronization "); + + time_t now = time(nullptr); + while (now < 24 * 3600) + { + Serial.print("."); + delay(100); + now = time(nullptr); + } + Serial.println(); + + Serial.print("Current time (unixtime): "); + Serial.println(now); +} + +int getMessageId(telegramMessage message) +{ + if (message.type == "callback_query") + { + Serial.println("callback_query detected. The message_id will be passed."); + } + + return message.type == "callback_query" ? message.message_id : 0; +} + +String getKeyboardJson(JsonDocument& keyboard) +{ + String keyboardJson = ""; + serializeJson(keyboard, keyboardJson); + return keyboardJson; +} \ No newline at end of file From 0dbcac3310c82e9bb599815e49c73f4e55dcf7dd Mon Sep 17 00:00:00 2001 From: Gemini_13 Date: Wed, 3 Nov 2021 02:00:43 +0200 Subject: [PATCH 5/8] Example for deleteMessage() and sendMessageWithInlineKeyboard() --- .../DeleteMessage/{InlineKeyboardMarkup.ino => DeleteMessage.ino} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/ESP8266/DeleteMessage/{InlineKeyboardMarkup.ino => DeleteMessage.ino} (100%) diff --git a/examples/ESP8266/DeleteMessage/InlineKeyboardMarkup.ino b/examples/ESP8266/DeleteMessage/DeleteMessage.ino similarity index 100% rename from examples/ESP8266/DeleteMessage/InlineKeyboardMarkup.ino rename to examples/ESP8266/DeleteMessage/DeleteMessage.ino From eae390e9ae108ce885f44ec5200009ff436421a8 Mon Sep 17 00:00:00 2001 From: Gemini_13 Date: Mon, 8 Nov 2021 02:29:02 +0200 Subject: [PATCH 6/8] Added parameter "disable_notification" for sendMessage() --- src/UniversalTelegramBot.cpp | 6 +++++- src/UniversalTelegramBot.h | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/UniversalTelegramBot.cpp b/src/UniversalTelegramBot.cpp index 3352cef..f696291 100644 --- a/src/UniversalTelegramBot.cpp +++ b/src/UniversalTelegramBot.cpp @@ -561,7 +561,8 @@ bool UniversalTelegramBot::sendSimpleMessage(const String& chat_id, const String } bool UniversalTelegramBot::sendMessage(const String& chat_id, const String& text, - const String& parse_mode, int message_id, bool disable_web_page_preview) { + const String& parse_mode, int message_id, bool disable_web_page_preview, + bool disable_notification) { DynamicJsonDocument payload(maxMessageLength); payload["chat_id"] = chat_id; @@ -576,6 +577,9 @@ bool UniversalTelegramBot::sendMessage(const String& chat_id, const String& text if (disable_web_page_preview) payload["disable_web_page_preview"] = disable_web_page_preview; + if (disable_notification) + payload["disable_notification"] = disable_notification; + return sendPostMessage(payload.as(), message_id); // if message id == 0 then edit is false, else edit is true } diff --git a/src/UniversalTelegramBot.h b/src/UniversalTelegramBot.h index 4932c5a..f5b73d9 100644 --- a/src/UniversalTelegramBot.h +++ b/src/UniversalTelegramBot.h @@ -84,7 +84,7 @@ class UniversalTelegramBot { bool sendSimpleMessage(const String& chat_id, const String& text, const String& parse_mode); bool sendMessage(const String& chat_id, const String& text, const String& parse_mode = "", int message_id = 0, - bool disable_web_page_preview = false); + bool disable_web_page_preview = false, bool disable_notification = false); bool deleteMessage(const String& chat_id, int message_id = 0); bool sendMessageWithReplyKeyboard(const String& chat_id, const String& text, const String& parse_mode, const String& keyboard, From ee144d1931b01e91a0802b2431eac2aadedc61f2 Mon Sep 17 00:00:00 2001 From: Gemini_13 Date: Mon, 8 Nov 2021 02:29:33 +0200 Subject: [PATCH 7/8] Updated README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8127696..e2e88e4 100644 --- a/README.md +++ b/README.md @@ -60,9 +60,10 @@ Here is a list of features that this library covers. (Note: The examples link to | Feature | Description | Usage | Example | | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | _Receiving Messages_ | Your bot can read messages that are sent to it. This is useful for sending commands to your arduino such as toggle and LED | `int getUpdates(long offset)`

Gets any pending messages from Telegram and stores them in **bot.messages** . Offset should be set to **bot.last_message_received** + 1. Returns the numbers new messages received. | [FlashLED](https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/blob/master/examples/ESP8266/FlashLED/FlashLED.ino) or any other example | -| _Sending messages_ | Your bot can send messages to any Telegram or group. This can be useful to get the arduino to notify you of an event e.g. Button pressed etc (Note: bots can only message you if you messaged them first) | `bool sendMessage(String chat_id, String text, String parse_mode = "")`

Sends the message to the chat_id. Returns if the message sent or not. | [EchoBot](https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/blob/master/examples/ESP8266/EchoBot/EchoBot.ino#L51) or any other example | +| _Sending messages_ | Your bot can send messages to any Telegram or group. This can be useful to get the arduino to notify you of an event e.g. Button pressed etc (Note: bots can only message you if you messaged them first) | `bool sendMessage(String chat_id, String text, String parse_mode = "", int message_id = 0, bool disable_web_page_preview = false, bool disable_notification = false)`

Sends the message to the chat_id. Returns if the message sent or not. | [EchoBot](https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/blob/master/examples/ESP8266/EchoBot/EchoBot.ino#L51) or any other example | | _Reply Keyboards_ | Your bot can send [reply keyboards](https://camo.githubusercontent.com/2116a60fa614bf2348074a9d7148f7d0a7664d36/687474703a2f2f692e696d6775722e636f6d2f325268366c42672e6a70673f32) that can be used as a type of menu. | `bool sendMessageWithReplyKeyboard(String chat_id, String text, String parse_mode, String keyboard, bool resize = false, bool oneTime = false, bool selective = false)`

Send a keyboard to the specified chat_id. parse_mode can be left blank. Will return true if the message sends successfully. | [ReplyKeyboard](https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/blob/master/examples/ESP8266/CustomKeyboard/ReplyKeyboardMarkup/ReplyKeyboardMarkup.ino) | | _Inline Keyboards_ | Your bot can send [inline keyboards](https://camo.githubusercontent.com/55dde972426e5bc77120ea17a9c06bff37856eb6/68747470733a2f2f636f72652e74656c656772616d2e6f72672f66696c652f3831313134303939392f312f324a536f55566c574b61302f346661643265323734336463386564613034).

Note: URLS & callbacks are supported currently | `bool sendMessageWithInlineKeyboard(String chat_id, String text, String parse_mode, String keyboard)`

Send a keyboard to the specified chat_id. parse_mode can be left blank. Will return true if the message sends successfully. | [InlineKeyboard](https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/blob/master/examples/ESP8266/CustomKeyboard/InlineKeyboardMarkup/InlineKeyboardMarkup.ino) | +| _Deleting messages_ | Your bot can delete messages | `bool deleteMessage(String chat_id, int message_id = 0)`

Deletes the message by message_id from the selected chat. Will return true if the message was successfully deleted. | [DeleteMessage](examples/ESP8266/DeleteMessage/DeleteMessage.ino) | | _Send Photos_ | It is possible to send phtos from your bot. You can send images from the web or from the arduino directly (Only sending from an SD card has been tested, but it should be able to send from a camera module) | Check the examples for more info | [From URL](https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/blob/master/examples/ESP8266/SendPhoto/PhotoFromURL/PhotoFromURL.ino)

[Binary from SD](https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/blob/master/examples/ESP8266/SendPhoto/PhotoFromSD/PhotoFromSD.ino)

[From File Id](https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/blob/master/examples/ESP8266/SendPhoto/PhotoFromFileID/PhotoFromFileID.ino) | | _Chat Actions_ | Your bot can send chat actions, such as _typing_ or _sending photo_ to let the user know that the bot is doing something. | `bool sendChatAction(String chat_id, String chat_action)`

Send a the chat action to the specified chat_id. There is a set list of chat actions that Telegram support, see the example for details. Will return true if the chat actions sends successfully. | | _Location_ | Your bot can receive location data, either from a single location data point or live location data. | Check the example. | [Location](https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/tree/master/examples/ESP8266/Location/Location.ino) | From 53892d7127559c6a524750caeeab9cb21568df33 Mon Sep 17 00:00:00 2001 From: Gemini_13 Date: Wed, 5 Jan 2022 04:28:40 +0200 Subject: [PATCH 8/8] Optimizations and skipping long messages --- src/UniversalTelegramBot.cpp | 97 +++++++++++++++++++++++++++++------- src/UniversalTelegramBot.h | 3 +- 2 files changed, 81 insertions(+), 19 deletions(-) diff --git a/src/UniversalTelegramBot.cpp b/src/UniversalTelegramBot.cpp index f696291..5a2759c 100644 --- a/src/UniversalTelegramBot.cpp +++ b/src/UniversalTelegramBot.cpp @@ -64,7 +64,7 @@ String UniversalTelegramBot::buildCommand(const String& cmd) { } String UniversalTelegramBot::sendGetToTelegram(const String& command) { - String body, headers; + String body; // Connect with api.telegram.org if not already connected if (!client->connected()) { @@ -91,27 +91,43 @@ String UniversalTelegramBot::sendGetToTelegram(const String& command) { client->println(F("Cache-Control: no-cache")); client->println(); - readHTTPAnswer(body, headers); + readHTTPAnswer(body); } return body; } -bool UniversalTelegramBot::readHTTPAnswer(String &body, String &headers) { +bool UniversalTelegramBot::readHTTPAnswer(String &body) { int ch_count = 0; unsigned long now = millis(); bool finishedHeaders = false; bool currentLineIsBlank = true; bool responseReceived = false; + int toRead = 0; + String headers; while (millis() - now < longPoll * 1000 + waitForResponse) { while (client->available()) { char c = client->read(); - responseReceived = true; if (!finishedHeaders) { if (currentLineIsBlank && c == '\n') { finishedHeaders = true; + + String headerLC = String(headers); + headerLC.toLowerCase(); + int ind1 = headerLC.indexOf("content-length"); + if (ind1 != -1) { + int ind2 = headerLC.indexOf("\r", ind1 + 15); + if (ind2 != -1) { + toRead = headerLC.substring(ind1 + 15, ind2).toInt(); + headers = ""; + #ifdef TELEGRAM_DEBUG + Serial.print(F("Content-Length: ")); + Serial.println(toRead); + #endif + } + } } else { headers += c; } @@ -119,6 +135,7 @@ bool UniversalTelegramBot::readHTTPAnswer(String &body, String &headers) { if (ch_count < maxMessageLength) { body += c; ch_count++; + responseReceived = toRead > 0 ? ch_count == toRead : true; } } @@ -127,21 +144,23 @@ bool UniversalTelegramBot::readHTTPAnswer(String &body, String &headers) { } if (responseReceived) { - #ifdef TELEGRAM_DEBUG - Serial.println(); - Serial.println(body); - Serial.println(); - #endif break; } } + + #ifdef TELEGRAM_DEBUG + Serial.println(F("Body:")); + Serial.println(body); + Serial.print(F("ch_count: ")); + Serial.println(ch_count); + #endif + return responseReceived; } String UniversalTelegramBot::sendPostToTelegram(const String& command, JsonObject payload) { String body; - String headers; // Connect with api.telegram.org if not already connected if (!client->connected()) { @@ -176,10 +195,11 @@ String UniversalTelegramBot::sendPostToTelegram(const String& command, JsonObjec client->println(out); #ifdef TELEGRAM_DEBUG - Serial.println(String("Posting:") + out); + Serial.print(F("Posting: ")); + Serial.println(out); #endif - readHTTPAnswer(body, headers); + readHTTPAnswer(body); } return body; @@ -194,7 +214,6 @@ String UniversalTelegramBot::sendMultipartFormDataToTelegram( GetNextBufferLen getNextBufferLenCallback) { String body; - String headers; const String boundary = F("------------------------b8f610217e83e29b"); @@ -252,7 +271,8 @@ String UniversalTelegramBot::sendMultipartFormDataToTelegram( client->print(start_request); #ifdef TELEGRAM_DEBUG - Serial.print("Start request: " + start_request); + Serial.print(F("Start request: ")); + Serial.println(start_request); #endif if (getNextByteCallback == nullptr) { @@ -291,9 +311,10 @@ String UniversalTelegramBot::sendMultipartFormDataToTelegram( client->print(end_request); #ifdef TELEGRAM_DEBUG - Serial.print("End request: " + end_request); + Serial.print(F("End request: ")); + Serial.println(end_request); #endif - readHTTPAnswer(body, headers); + readHTTPAnswer(body); } closeClient(); @@ -337,7 +358,8 @@ bool UniversalTelegramBot::setMyCommands(const String& commandArray) { while (millis() - sttime < 8000ul) { // loop for a while to send the message response = sendPostToTelegram(BOT_CMD("setMyCommands"), payload.as()); #ifdef TELEGRAM_DEBUG - Serial.println("setMyCommands response" + response); + Serial.println(F("setMyCommands response:")); + Serial.println(response); #endif sent = checkForOkResponse(response); if (sent) break; @@ -368,6 +390,7 @@ int UniversalTelegramBot::getUpdates(long offset) { command += String(longPoll); } String response = sendGetToTelegram(command); // receive reply from telegram.org + long updateId = getUpdateIdFromResponse(response); if (response == "") { #ifdef TELEGRAM_DEBUG @@ -416,6 +439,9 @@ int UniversalTelegramBot::getUpdates(long offset) { #endif } } else { // Parsing failed + Serial.print(F("Update ID with error: ")); + Serial.println(updateId); + if (response.length() < 2) { // Too short a message. Maybe a connection issue #ifdef TELEGRAM_DEBUG Serial.println(F("Parsing error: Message too short")); @@ -432,6 +458,15 @@ int UniversalTelegramBot::getUpdates(long offset) { } // Close the client as no response is to be given closeClient(); + + if (error && response.length() == (unsigned) maxMessageLength) { + Serial.print(F("The message with update ID ")); + Serial.print(updateId); + Serial.println(F(" is too long and was skipped. The next update ID has been sent for processing.")); + + return getUpdates(updateId + 1); + } + return 0; } } @@ -651,7 +686,7 @@ bool UniversalTelegramBot::sendMessageWithInlineKeyboard(const String& chat_id, const String& text, const String& parse_mode, const String& keyboard, - int message_id) { // added message_id + int message_id) { DynamicJsonDocument payload(maxMessageLength); payload["chat_id"] = chat_id; @@ -860,3 +895,29 @@ bool UniversalTelegramBot::answerCallbackQuery(const String &query_id, const Str closeClient(); return answer; } + +long UniversalTelegramBot::getUpdateIdFromResponse(String response) { + response.remove(response.indexOf("\n")); + + char updateId[20]; + const char *str = response.c_str(); + + while(*str != '\0') + { + if (*str == '\r') { + break; + } + + str++; + + int i = 0; + while('0' <= *str && *str <= '9') + { + updateId[i] = *str; + i++; + str++; + } + } + + return atol(updateId); +} \ No newline at end of file diff --git a/src/UniversalTelegramBot.h b/src/UniversalTelegramBot.h index f5b73d9..41e5f1a 100644 --- a/src/UniversalTelegramBot.h +++ b/src/UniversalTelegramBot.h @@ -79,7 +79,7 @@ class UniversalTelegramBot { GetNextBuffer getNextBufferCallback, GetNextBufferLen getNextBufferLenCallback); - bool readHTTPAnswer(String &body, String &headers); + bool readHTTPAnswer(String &body); bool getMe(); bool sendSimpleMessage(const String& chat_id, const String& text, const String& parse_mode); @@ -135,6 +135,7 @@ class UniversalTelegramBot { void closeClient(); bool getFile(String& file_path, long& file_size, const String& file_id); bool processResult(JsonObject result, int messageIndex); + long getUpdateIdFromResponse(String response); }; #endif