Skip to content

Fix by RobertGnz for too long messages and new function deleteMessage #348

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

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
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
6 changes: 2 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,7 @@ Each library only supported a single type of Arduino and had different features

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


## Installing

The downloaded code can be included as a new library into the IDE selecting the menu:
Expand Down Expand Up @@ -70,6 +67,7 @@ Here is a list of features that this library covers. (Note: The examples link to
| _Long Poll_ | Set how long the bot will wait checking for a new message before returning now messages. <br><br> This will decrease the amount of requests and data used by the bot, but it will tie up the arduino while it waits for messages | `bot.longPoll = 60;` <br><br> Where 60 is the amount of seconds it should wait | [LongPoll](https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/tree/master/examples/ESP8266/LongPoll/LongPoll.ino) |
| _Update Firmware and SPIFFS_ | You can update firmware and spiffs area through send files as a normal file with a specific caption. | `update firmware` <br>or<br>`update spiffs`<br> These are captions for example. | [telegramOTA](https://github.com/solcer/Universal-Arduino-Telegram-Bot/blob/master/examples/ESP32/telegramOTA/telegramOTA.ino) | ``` |
| _Set bot's commands_ | You can set bot commands programmatically from your code. The commands will be shown in a special place in the text input area | `bot.setMyCommands("[{\"command\":\"help\", \"description\":\"get help\"},{\"command\":\"start\",\"description\":\"start conversation\"}]");`. See examples | [SetMyCommands](examples/ESP8266/SetMyCommands/SetMyCommands.ino) |
| _Deleting messages_ | Your bot can delete a message. This can be useful to delete unwanted messages from Spambots e.g. | `bool deleteMessage(String chat_id, int message_id)` <br><br> Deletes the message from chat_id with the message_id. Returns true if successful. | |

The full Telegram Bot API documentation can be read [here](https://core.telegram.org/bots/api). If there is a feature you would like added to the library please either raise a Github issue or please feel free to raise a Pull Request.

Expand Down
104 changes: 89 additions & 15 deletions src/UniversalTelegramBot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,14 +328,14 @@ bool UniversalTelegramBot::setMyCommands(const String& commandArray) {
payload["commands"] = serialized(commandArray);
bool sent = false;
String response = "";
#if defined(_debug)
#ifdef TELEGRAM_DEBUG
Serial.println(F("sendSetMyCommands: SEND Post /setMyCommands"));
#endif // defined(_debug)
#endif
unsigned long sttime = millis();

while (millis() - sttime < 8000ul) { // loop for a while to send the message
response = sendPostToTelegram(BOT_CMD("setMyCommands"), payload.as<JsonObject>());
#ifdef _debug
#ifdef TELEGRAM_DEBUG
Serial.println("setMyCommands response" + response);
#endif
sent = checkForOkResponse(response);
Expand Down Expand Up @@ -367,15 +367,38 @@ int UniversalTelegramBot::getUpdates(long offset) {
command += String(longPoll);
}
String response = sendGetToTelegram(command); // receive reply from telegram.org

// RobertGnz: 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.
// See: https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/issues/275
// and: https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/issues/266#issuecomment-985013894
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 +409,12 @@ int UniversalTelegramBot::getUpdates(long offset) {
DynamicJsonDocument doc(maxMessageLength);
DeserializationError error = deserializeJson(doc, ZERO_COPY(response));

if (!error) {
// Not, if response is too long (maxResponseLength in UniversalTelegramBot.h in L135)
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 +439,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
// serial 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
}
// RobertGnz: try to update last_message_received
if ( candidate != -1 ) last_message_received = candidate;
// End RobertGnz

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 @@ -809,11 +848,46 @@ bool UniversalTelegramBot::answerCallbackQuery(const String &query_id, const Str
if (url.length() > 0) payload["url"] = url;

String response = sendPostToTelegram(BOT_CMD("answerCallbackQuery"), payload.as<JsonObject>());
#ifdef _debug
#ifdef TELEGRAM_DEBUG
Serial.print(F("answerCallbackQuery response:"));
Serial.println(response);
#endif
bool answer = checkForOkResponse(response);
closeClient();
return answer;
}

/***********************************************************************
* 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<JsonObject>());
#ifdef TELEGRAM_DEBUG
Serial.print(F("deleteMessage response:"));
Serial.println(response);
#endif

bool sent = checkForOkResponse(response);
closeClient();
return sent;
}
5 changes: 3 additions & 2 deletions src/UniversalTelegramBot.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef UniversalTelegramBot_h
#define UniversalTelegramBot_h

//#define TELEGRAM_DEBUG 1
#define ARDUINOJSON_DECODE_UNICODE 1
#define ARDUINOJSON_USE_LONG_LONG 1
#include <Arduino.h>
Expand All @@ -35,7 +34,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define HANDLE_MESSAGES 1

//unmark following line to enable debug mode
//#define _debug
// #define TELEGRAM_DEBUG

typedef bool (*MoreDataAvailable)();
typedef byte (*GetNextByte)();
Expand Down Expand Up @@ -86,6 +85,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 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 @@ -127,6 +127,7 @@ class UniversalTelegramBot {
int _lastError;
int last_sent_message_id = 0;
int maxMessageLength = 1500;
unsigned int maxResponseLength = 1500;

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