-
Notifications
You must be signed in to change notification settings - Fork 311
Description
There is a BUG in UniversalTelegramBot::getUpdates() function:
If deserializeJson happen to endup with an error for instance update to big for the buffer, then "last_message_received" is not updated and the function returns 0.
Subsequent calls to getUpdates uses "last_message_received + 1" for the offset value which is passed to getUpdates.
But as last_message_received was not updated, getUpdates will allways read the same message. deserializeJson will always endup with the same error and getUpdates will always return 0.
I propose the following changes in two places of UniversalTelegramBot::getUpdates. To make them easier to find in the code, changes begin with // Robert and ends with // End Robert
Please see below.
int UniversalTelegramBot::getUpdates(long offset) {
#ifdef TELEGRAM_DEBUG
Serial.println(F("GET Update Messages"));
#endif
String command = BOT_CMD("getUpdates?offset=");
command += offset;
command += F("&limit=");
command += HANDLE_MESSAGES;
if (longPoll > 0) {
command += F("&timeout=");
command += String(longPoll);
}
String response = sendGetToTelegram(command); // receive reply from telegram.org
// Robert:
// If deserializeJson happen to endup with an error for instance update to big for
// the buffer, then last_message_received will not be updated.
// Subsequent calls to getUpdates uses last_message_received + 1 for the offset value.
// But as last_message_received was not updated we will allways read the same message.
// Here we try to find the update_id and store it to update last_message_received if necessary.
char * pt1; char * pt2; long candidate;
candidate = -1;
pt1 = strstr_P( response.c_str(), (const char *) F("update_id"));
if ( pt1 != NULL ) {
pt1 = strstr_P( pt1, (const char *) F(":"));
if ( pt1 != NULL ) {
pt1++;
pt2 = strstr_P( pt1, (const char *) F(","));
if ( pt2 != NULL ) {
if ( pt2 - pt1 < 12 ) { // for safety
sscanf( pt1, "%ld", &candidate );
}
}
}
}
// End Robert
if (response == "") {
#ifdef TELEGRAM_DEBUG
Serial.println(F("Received empty string in response!"));
#endif
// close the client as there's nothing to do with an empty string
closeClient();
return 0;
} else {
#ifdef TELEGRAM_DEBUG
Serial.print(F("incoming message length "));
Serial.println(response.length());
Serial.println(F("Creating DynamicJsonBuffer"));
#endif
// Parse response into Json object
DynamicJsonDocument doc(maxMessageLength);
DeserializationError error = deserializeJson(doc, ZERO_COPY(response));
if (!error) {
#ifdef TELEGRAM_DEBUG
Serial.print(F("GetUpdates parsed jsonObj: "));
serializeJson(doc, Serial);
Serial.println();
#endif
if (doc.containsKey("result")) {
int resultArrayLength = doc["result"].size();
if (resultArrayLength > 0) {
int newMessageIndex = 0;
// Step through all results
for (int i = 0; i < resultArrayLength; i++) {
JsonObject result = doc["result"][i];
if (processResult(result, newMessageIndex)) newMessageIndex++;
}
// We will keep the client open because there may be a response to be
// given
return newMessageIndex;
} else {
#ifdef TELEGRAM_DEBUG
Serial.println(F("no new messages"));
#endif
}
} else {
#ifdef TELEGRAM_DEBUG
Serial.println(F("Response contained no 'result'"));
#endif
}
} else { // Parsing failed
// Robert: try to update last_message_received
if ( candidate != -1 ) last_message_received = candidate;
// End Robert
if (response.length() < 2) { // Too short a message. Maybe a connection issue
#ifdef TELEGRAM_DEBUG
Serial.println(F("Parsing error: Message too short"));
#endif
} else {
// Buffer may not be big enough, increase buffer or reduce max number of
// messages
#ifdef TELEGRAM_DEBUG
Serial.print(F("Failed to parse update, the message could be too "
"big for the buffer. Error code: "));
Serial.println(error.c_str()); // debug print of parsing error
#endif
}
}
// Close the client as no response is to be given
closeClient();
return 0;
}
}