Skip to content

Fix from RobertGnz about issue with too long messages (#275) #296

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@
.gcc-flags.json
.pio/
.vscode/
descript.ion
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ An Arduino IDE library for using Telegram Bot API. It's designed to be used with

Join the [Arduino Telegram Library Group Chat](https://t.me/arduino_telegram_library) if you have any questions/feedback or would just like to be kept up to date with the library's progress.

## Help support what I do!

I have created a lot of different Arduino libraries that I hope people can make use of. [If you enjoy my work, please consider becoming a Github sponsor!](https://github.com/sponsors/witnessmenow/)

## Introduction

This library provides an interface for [Telegram Bot API](https://core.telegram.org/bots/api).
Expand All @@ -24,6 +20,12 @@ Each library only supported a single type of Arduino and had different features

![alt text](https://imgs.xkcd.com/comics/standards.png "standards")

Finally I have forked this library, which is since years no more under development, from witnessmenow and I have implemented the fix of [issue #275](https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/issues/275) by glorious developer [RobertGnz](https://github.com/RobertGnz) (Thank you!).

Furhter I have implemented a new API-Call deleteMessage (see UniversalTelegramBot::deleteMessage in the src), to easier ban a chat_id if some flooding attack would happen.

There is still much work to do: the strings in the library will crash the ESP8266 after a while of running, because of memory issues, see: [Taming Arduino Strings -- How to Avoid Memory Issues](https://www.instructables.com/Taming-Arduino-Strings-How-to-Avoid-Memory-Issues/). J-Rios has already done good work here with his [fork](https://github.com/J-Rios/Universal-Arduino-Telegram-Bot) but it is back in commits (compared to witnessmenow's repo) a lot. Maybe it is possible to use some special string library, e.g. [SafeString](https://www.forward.com.au/pfod/ArduinoProgramming/SafeString/index.html). At the moment I do [daily reset](https://www.forward.com.au/pfod/ArduinoProgramming/ArduinoStrings/index.html#reboot) to avoid memory issues.

## Installing

The downloaded code can be included as a new library into the IDE selecting the menu:
Expand Down
95 changes: 85 additions & 10 deletions src/UniversalTelegramBot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@

#define ZERO_COPY(STR) ((char*)STR.c_str())
#define BOT_CMD(STR) buildCommand(F(STR))
// fcw: 2022-07-13: DEBUG
// #define TELEGRAM_DEBUG

UniversalTelegramBot::UniversalTelegramBot(const String& token, Client &client) {
updateToken(token);
Expand Down Expand Up @@ -368,14 +370,45 @@ int UniversalTelegramBot::getUpdates(long offset) {
}
String response = sendGetToTelegram(command); // receive reply from telegram.org

// fcw: 2022-07-13: Bug bei zu grossen Nachrichten, die werden immer wieder abgerufen und blockieren die Abfrage
// so gemacht mit einer 1500 Zeichen grossen Nachricht von Cat (5306541440), danach ging es nicht mehr.
// RobertGnz hat dazu schon einen issue geoeffnet, siehe:
// https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/issues/275
// Aenderungen sind mit // Robert und // End Robert gerahmt (hier und weiter unten noch eine Zeile).
// Nach der Aenderung von Robert ging es wieder.
// Siehe auch: https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/issues/266#issuecomment-985013894

// Robert:
// If deserializeJson happen to endup with an error for instance update too 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 {
}
else {
#ifdef TELEGRAM_DEBUG
Serial.print(F("incoming message length "));
Serial.println(response.length());
Expand All @@ -386,11 +419,12 @@ int UniversalTelegramBot::getUpdates(long offset) {
DynamicJsonDocument doc(maxMessageLength);
DeserializationError error = deserializeJson(doc, ZERO_COPY(response));

if (!error) {
// fcw: 2022-09-28: Hack. Nicht, wenn response zu lang (maxResponseLength in der Header Z135)
if ((!error) && (response.length() < maxResponseLength)) {
#ifdef TELEGRAM_DEBUG
Serial.print(F("GetUpdates parsed jsonObj: "));
serializeJson(doc, Serial);
Serial.println();
Serial.println();
#endif
if (doc.containsKey("result")) {
int resultArrayLength = doc["result"].size();
Expand All @@ -415,20 +449,35 @@ int UniversalTelegramBot::getUpdates(long offset) {
#endif
}
} else { // Parsing failed
if (response.length() < 2) { // Too short a message. Maybe a connection issue
#ifdef TELEGRAM_DEBUG
// fcw: fuer Seriellen Debug
if (response.length() >= maxResponseLength) {
#ifdef TELEGRAM_DEBUG
Serial.print(F("Received too long string in response! response.length(): "));
Serial.println(response.length());
Serial.print(F("last_message_received: "));
Serial.println(last_message_received);
Serial.print(F("candidate: "));
Serial.println(candidate);
#endif
}
// 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 {
#endif
} else {
// Buffer may not be big enough, increase buffer or reduce max number of
// messages
#ifdef TELEGRAM_DEBUG
#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
#endif
}
}
}
// Close the client as no response is to be given
closeClient();
return 0;
Expand Down Expand Up @@ -817,3 +866,29 @@ bool UniversalTelegramBot::answerCallbackQuery(const String &query_id, const Str
closeClient();
return answer;
}

// fcw: 2022-09-19: um Nachrichten zu loeschen, kopiert und angepasst von sendSimpleMessage(...)
bool UniversalTelegramBot::deleteMessage(const String& chat_id, int message_id) {
bool sent = false;
#ifdef TELEGRAM_DEBUG
Serial.println(F("deleteMessage: DELETE Message"));
#endif
unsigned long sttime = millis();

if (chat_id != "" && message_id != 0) {
while (millis() - sttime < 8000ul) { // loop for a while to send the message
String command = BOT_CMD("deleteMessage?chat_id=");
command += chat_id;
command += F("&message_id=");
command += String(message_id);
String response = sendGetToTelegram(command);
#ifdef TELEGRAM_DEBUG
Serial.println(response);
#endif
sent = checkForOkResponse(response);
if (sent) break;
}
}
closeClient();
return sent;
}
8 changes: 7 additions & 1 deletion src/UniversalTelegramBot.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef UniversalTelegramBot_h
#define UniversalTelegramBot_h

//#define TELEGRAM_DEBUG 1
// fcw: hier wird der Bibliotheks Debug-Schalter gesetzt (entkommentiert fuer seriellen DEBUG)
// #define TELEGRAM_DEBUG 1
#define ARDUINOJSON_DECODE_UNICODE 1
#define ARDUINOJSON_USE_LONG_LONG 1
#include <Arduino.h>
Expand Down Expand Up @@ -86,6 +87,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);
// fcw: 2022-09-19: Nachrichten loeschen...
bool deleteMessage(const String& chat_id, int message_id);
bool sendMessageWithReplyKeyboard(const String& chat_id, const String& text,
const String& parse_mode, const String& keyboard,
bool resize = false, bool oneTime = false,
Expand Down Expand Up @@ -126,7 +129,10 @@ class UniversalTelegramBot {
unsigned int waitForResponse = 1500;
int _lastError;
int last_sent_message_id = 0;
// fcw: 2022-09-27: wenn maxMessageLength kleiner geht es aber nicht mehr.
int maxMessageLength = 1500;
// fcw: Antwort Laenge beschraenken, damit Flooding nicht auch noch zurueck gesendet wird. Laenge der Antwort: siehe response.length() Achtung: ohne Inhalt (text) ist die Laenge schon 356 gross. Maximaler Befehl (/open_with_supercode...) ist 391 Zeichen insgesamt
unsigned int maxResponseLength = 400;

private:
// JsonObject * parseUpdates(String response);
Expand Down