Skip to content

Commit 262757c

Browse files
authored
Merge pull request #203 from witnessmenow/pr/190
Pr/190 - Message_id added in order to UPDATE messages and inlinekeyboard BUTTONS
2 parents 4ff1911 + 1307102 commit 262757c

File tree

5 files changed

+228
-15
lines changed

5 files changed

+228
-15
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ env:
3131
- SCRIPT=platformioSingle EXAMPLE_NAME=ChatAction EXAMPLE_FOLDER=/ BOARDTYPE=ESP32 BOARD=esp32dev
3232
- SCRIPT=platformioSingle EXAMPLE_NAME=InlineKeyboardMarkup EXAMPLE_FOLDER=/CustomKeyboard/ BOARDTYPE=ESP32 BOARD=esp32dev
3333
- SCRIPT=platformioSingle EXAMPLE_NAME=ReplyKeyboardMarkup EXAMPLE_FOLDER=/CustomKeyboard/ BOARDTYPE=ESP32 BOARD=esp32doit-devkit-v1
34+
- SCRIPT=platformioSingle EXAMPLE_NAME=UpdateInlineKeyboard EXAMPLE_FOLDER=/CustomKeyboard/ BOARDTYPE=ESP32 BOARD=esp32dev
3435
- SCRIPT=platformioSingle EXAMPLE_NAME=EchoBot EXAMPLE_FOLDER=/ BOARDTYPE=ESP32 BOARD=esp32dev
3536
- SCRIPT=platformioSingle EXAMPLE_NAME=FlashLED EXAMPLE_FOLDER=/ BOARDTYPE=ESP32 BOARD=esp32doit-devkit-v1
3637
- SCRIPT=platformioSingle EXAMPLE_NAME=Location EXAMPLE_FOLDER=/ BOARDTYPE=ESP32 BOARD=esp32dev
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#ESP32 - LED button update
2+
3+
This is an example of how one can update inline keyboard messages (buttons).
4+
The message_id of the specific message is sent when a message is received.
5+
This message_id can be used to UPDATE that message.
6+
One can update text inside a message, but also buttons can be updated.
7+
This way one can build menu's, like the menu the botfather uses.
8+
9+
In this simple example we use a inlinekeyboard button to toggle (and update) the state of a LED.
10+
11+
NOTE: You will need to enter your SSID, password and bot Token for the example to work.
12+
13+
Example and update to Universal-Arduino-Telegram-Bot originally written by
14+
[Frits Jan van Kempen] (https://github.com/fritsjan) with inspiration from [RomeHein] (https://github.com/RomeHein)
15+
16+
Adapted by [Brian Lough](https://github.com/witnessmenow)
17+
18+
## License
19+
20+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
21+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/*******************************************************************
2+
An example to show how to edit an existing inline keyboard.
3+
4+
In this example the keyboard is updated with the state of
5+
the LED.
6+
7+
written by Frits Jan van Kempen
8+
*******************************************************************/
9+
#include <Arduino.h>
10+
#include <WiFi.h>
11+
#include <WiFiClientSecure.h>
12+
#include <UniversalTelegramBot.h>
13+
14+
// Initialize Wifi connection to the router
15+
const char *ssid = "mySSID";
16+
const char *password = "myPASSWORD";
17+
18+
// Initialize Telegram BOT
19+
#define BOTtoken "xxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxx" // your Bot Token (Get from Botfather)
20+
WiFiClientSecure client;
21+
UniversalTelegramBot bot(BOTtoken, client);
22+
23+
int Bot_mtbs = 1000; //mean time between scan messages
24+
long Bot_lasttime; //last time messages' scan has been done
25+
int last_message_id = 0;
26+
27+
// LED parameters
28+
const int ledPin = 2; // Internal LED on DevKit ESP32-WROOM (GPIO2)
29+
int ledState = LOW;
30+
31+
void handleNewMessages(int numNewMessages)
32+
{
33+
34+
for (int i = 0; i < numNewMessages; i++)
35+
{
36+
37+
// Get all the important data from the message
38+
int message_id = bot.messages[i].message_id;
39+
String chat_id = String(bot.messages[i].chat_id);
40+
String text = bot.messages[i].text;
41+
String from_name = bot.messages[i].from_name;
42+
if (from_name == "")
43+
from_name = "Guest";
44+
String msg = ""; // init a message string to use
45+
46+
// Output the message_id to give you feeling on how this example works
47+
Serial.print("Message id: ");
48+
Serial.println(message_id);
49+
50+
// Inline buttons with callbacks when pressed will raise a callback_query message
51+
if (bot.messages[i].type == "callback_query")
52+
{
53+
Serial.print("Call back button pressed by: ");
54+
Serial.println(bot.messages[i].from_id);
55+
Serial.print("Data on the button: ");
56+
Serial.println(bot.messages[i].text);
57+
58+
if (text == "/toggleLED")
59+
{
60+
61+
// Toggle the ledState and update the LED itself
62+
ledState = !ledState;
63+
digitalWrite(ledPin, ledState);
64+
65+
// Now we can UPDATE the message, lets prepare it for sending:
66+
msg = "Hi " + from_name + "!\n";
67+
msg += "Notice how the LED state has changed!\n\n";
68+
msg += "Try it again, see the button has updated as well:\n\n";
69+
70+
// Prepare the buttons
71+
String keyboardJson = "["; // start Json
72+
keyboardJson += "[{ \"text\" : \"The LED is ";
73+
if (ledState)
74+
{
75+
keyboardJson += "ON";
76+
}
77+
else
78+
{
79+
keyboardJson += "OFF";
80+
}
81+
keyboardJson += "\", \"callback_data\" : \"/toggleLED\" }]";
82+
keyboardJson += ", [{ \"text\" : \"Send text\", \"callback_data\" : \"This text was sent by inline button\" }]"; // add another button
83+
//keyboardJson += ", [{ \"text\" : \"Go to Google\", \"url\" : \"https://www.google.com\" }]"; // add another button, this one appears after first Update
84+
keyboardJson += "]"; // end Json
85+
86+
// Now send this message including the current message_id as the 5th input to UPDATE that message
87+
bot.sendMessageWithInlineKeyboard(chat_id, msg, "Markdown", keyboardJson, message_id);
88+
}
89+
90+
else
91+
{
92+
// echo back callback_query which is not handled above
93+
bot.sendMessage(chat_id, text, "Markdown");
94+
}
95+
}
96+
97+
// 'Normal' messages are handled here
98+
else
99+
{
100+
if (text == "/start")
101+
{
102+
// lets create a friendly welcome message
103+
msg = "Hi " + from_name + "!\n";
104+
msg += "I am your Telegram Bot running on ESP32.\n\n";
105+
msg += "Lets test this updating LED button below:\n\n";
106+
107+
// lets create a button depending on the current ledState
108+
String keyboardJson = "["; // start of keyboard json
109+
keyboardJson += "[{ \"text\" : \"The LED is ";
110+
if (ledState)
111+
{
112+
keyboardJson += "ON";
113+
}
114+
else
115+
{
116+
keyboardJson += "OFF";
117+
}
118+
keyboardJson += "\", \"callback_data\" : \"/toggleLED\" }]"; //callback is /toggleLED
119+
keyboardJson += ", [{ \"text\" : \"Send text\", \"callback_data\" : \"This text was sent by inline button\" }]"; // add another button
120+
keyboardJson += "]"; // end of keyboard json
121+
122+
//first time, send this message as a normal inline keyboard message:
123+
bot.sendMessageWithInlineKeyboard(chat_id, msg, "Markdown", keyboardJson);
124+
}
125+
if (text == "/options")
126+
{
127+
String keyboardJson = "[[{ \"text\" : \"Go to Google\", \"url\" : \"https://www.google.com\" }], [{ \"text\" : \"Send\", \"callback_data\" : \"This was sent by inline\" }]]";
128+
bot.sendMessageWithInlineKeyboard(chat_id, "Choose from one of the following options", "", keyboardJson);
129+
}
130+
}
131+
}
132+
}
133+
134+
void setup()
135+
{
136+
Serial.begin(115200);
137+
138+
// Attempt to connect to Wifi network:
139+
Serial.print("Connecting Wifi: ");
140+
Serial.println(ssid);
141+
142+
// Set WiFi to station mode and disconnect from an AP if it was Previously
143+
// connected
144+
WiFi.mode(WIFI_STA);
145+
WiFi.begin(ssid, password);
146+
147+
while (WiFi.status() != WL_CONNECTED)
148+
{
149+
Serial.print(".");
150+
delay(500);
151+
}
152+
153+
Serial.println("");
154+
Serial.println("WiFi connected");
155+
Serial.print("IP address: ");
156+
Serial.println(WiFi.localIP());
157+
158+
pinMode(ledPin, OUTPUT); // initialize ledPin as an output.
159+
digitalWrite(ledPin, ledState); // initialize pin as low (LED Off)
160+
}
161+
162+
void loop()
163+
{
164+
// run this in loop to poll new messages
165+
if (millis() > Bot_lasttime + Bot_mtbs)
166+
{
167+
int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
168+
169+
while (numNewMessages)
170+
{
171+
Serial.println("got response");
172+
handleNewMessages(numNewMessages);
173+
numNewMessages = bot.getUpdates(bot.last_message_received + 1);
174+
}
175+
176+
Bot_lasttime = millis();
177+
}
178+
}

src/UniversalTelegramBot.cpp

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ String UniversalTelegramBot::sendMultipartFormDataToTelegram(
235235
client->print(buildCommand(command));
236236
client->println(F(" HTTP/1.1"));
237237
// Host header
238-
client->print(F("Host: " TELEGRAM_HOST));
238+
client->println(F("Host: " TELEGRAM_HOST)); // bugfix - https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/issues/186
239239
client->println(F("User-Agent: arduino/1.0"));
240240
client->println(F("Accept: */*"));
241241

@@ -267,7 +267,6 @@ String UniversalTelegramBot::sendMultipartFormDataToTelegram(
267267
#endif
268268
byte buffer[512];
269269
int count = 0;
270-
271270
while (moreDataAvailableCallback()) {
272271
buffer[count] = getNextByteCallback();
273272
count++;
@@ -460,6 +459,7 @@ bool UniversalTelegramBot::processResult(JsonObject result, int messageIndex) {
460459
messages[messageIndex].chat_id = message["chat"]["id"].as<String>();
461460
messages[messageIndex].chat_title = message["chat"]["title"].as<String>();
462461
messages[messageIndex].hasDocument = false;
462+
messages[messageIndex].message_id = message["message_id"].as<int>(); // added message id
463463
if (message.containsKey("text")) {
464464
messages[messageIndex].text = message["text"].as<String>();
465465

@@ -479,14 +479,16 @@ bool UniversalTelegramBot::processResult(JsonObject result, int messageIndex) {
479479
messages[messageIndex].reply_to_message_id = message["reply_to_message"]["message_id"];
480480
// no need to check if containsKey["text"]. If it doesn't, it default to null
481481
messages[messageIndex].reply_to_text = message["reply_to_message"]["text"].as<String>();
482-
}
482+
}
483+
483484
} else if (result.containsKey("channel_post")) {
484485
JsonObject message = result["channel_post"];
485486
messages[messageIndex].type = F("channel_post");
486487
messages[messageIndex].text = message["text"].as<String>();
487488
messages[messageIndex].date = message["date"].as<String>();
488489
messages[messageIndex].chat_id = message["chat"]["id"].as<String>();
489490
messages[messageIndex].chat_title = message["chat"]["title"].as<String>();
491+
messages[messageIndex].message_id = message["message_id"].as<int>(); // added message id
490492

491493
} else if (result.containsKey("callback_query")) {
492494
JsonObject message = result["callback_query"];
@@ -499,6 +501,8 @@ bool UniversalTelegramBot::processResult(JsonObject result, int messageIndex) {
499501
messages[messageIndex].reply_to_text = message["message"]["text"].as<String>();
500502
messages[messageIndex].chat_title = F("");
501503
messages[messageIndex].query_id = message["id"].as<String>();
504+
messages[messageIndex].message_id = message["message"]["message_id"].as<int>(); // added message id
505+
502506
} else if (result.containsKey("edited_message")) {
503507
JsonObject message = result["edited_message"];
504508
messages[messageIndex].type = F("edited_message");
@@ -507,6 +511,7 @@ bool UniversalTelegramBot::processResult(JsonObject result, int messageIndex) {
507511
messages[messageIndex].date = message["date"].as<String>();
508512
messages[messageIndex].chat_id = message["chat"]["id"].as<String>();
509513
messages[messageIndex].chat_title = message["chat"]["title"].as<String>();
514+
messages[messageIndex].message_id = message["message_id"].as<int>(); // added message id
510515

511516
if (message.containsKey("text")) {
512517
messages[messageIndex].text = message["text"].as<String>();
@@ -555,16 +560,19 @@ bool UniversalTelegramBot::sendSimpleMessage(const String& chat_id, const String
555560
}
556561

557562
bool UniversalTelegramBot::sendMessage(const String& chat_id, const String& text,
558-
const String& parse_mode) {
563+
const String& parse_mode, int message_id) { // added message_id
559564

560565
DynamicJsonDocument payload(maxMessageLength);
561566
payload["chat_id"] = chat_id;
562567
payload["text"] = text;
563568

569+
if (message_id != 0)
570+
payload["message_id"] = message_id; // added message_id
571+
564572
if (parse_mode != "")
565573
payload["parse_mode"] = parse_mode;
566574

567-
return sendPostMessage(payload.as<JsonObject>());
575+
return sendPostMessage(payload.as<JsonObject>(), message_id); // if message id == 0 then edit is false, else edit is true
568576
}
569577

570578
bool UniversalTelegramBot::sendMessageWithReplyKeyboard(
@@ -599,25 +607,29 @@ bool UniversalTelegramBot::sendMessageWithReplyKeyboard(
599607
bool UniversalTelegramBot::sendMessageWithInlineKeyboard(const String& chat_id,
600608
const String& text,
601609
const String& parse_mode,
602-
const String& keyboard) {
610+
const String& keyboard,
611+
int message_id) { // added message_id
603612

604613
DynamicJsonDocument payload(maxMessageLength);
605614
payload["chat_id"] = chat_id;
606615
payload["text"] = text;
607616

617+
if (message_id != 0)
618+
payload["message_id"] = message_id; // added message_id
619+
608620
if (parse_mode != "")
609621
payload["parse_mode"] = parse_mode;
610622

611623
JsonObject replyMarkup = payload.createNestedObject("reply_markup");
612624
replyMarkup["inline_keyboard"] = serialized(keyboard);
613-
return sendPostMessage(payload.as<JsonObject>());
625+
return sendPostMessage(payload.as<JsonObject>(), message_id); // if message id == 0 then edit is false, else edit is true
614626
}
615627

616628
/***********************************************************************
617-
* SendPostMessage - function to send message to telegram *
629+
* SendPostMessage - function to send message to telegram *
618630
* (Arguments to pass: chat_id, text to transmit and markup(optional)) *
619631
***********************************************************************/
620-
bool UniversalTelegramBot::sendPostMessage(JsonObject payload) {
632+
bool UniversalTelegramBot::sendPostMessage(JsonObject payload, bool edit) { // added message_id
621633

622634
bool sent = false;
623635
#ifdef TELEGRAM_DEBUG
@@ -628,9 +640,9 @@ bool UniversalTelegramBot::sendPostMessage(JsonObject payload) {
628640
unsigned long sttime = millis();
629641

630642
if (payload.containsKey("text")) {
631-
while (millis() - sttime < 8000ul) { // loop for a while to send the message
632-
String response = sendPostToTelegram(BOT_CMD("sendMessage"), payload);
633-
#ifdef TELEGRAM_DEBUG
643+
while (millis() < sttime + 8000) { // loop for a while to send the message
644+
String response = sendPostToTelegram((edit ? BOT_CMD("editMessageText") : BOT_CMD("sendMessage")), payload); // if edit is true we send a editMessageText CMD
645+
#ifdef TELEGRAM_DEBUG
634646
Serial.println(response);
635647
#endif
636648
sent = checkForOkResponse(response);

src/UniversalTelegramBot.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ struct telegramMessage {
5858
float longitude;
5959
float latitude;
6060
int update_id;
61+
int message_id;
6162

6263
int reply_to_message_id;
6364
String reply_to_text;
@@ -84,17 +85,17 @@ class UniversalTelegramBot {
8485
bool getMe();
8586

8687
bool sendSimpleMessage(const String& chat_id, const String& text, const String& parse_mode);
87-
bool sendMessage(const String& chat_id, const String& text, const String& parse_mode = "");
88+
bool sendMessage(const String& chat_id, const String& text, const String& parse_mode = "", int message_id = 0);
8889
bool sendMessageWithReplyKeyboard(const String& chat_id, const String& text,
8990
const String& parse_mode, const String& keyboard,
9091
bool resize = false, bool oneTime = false,
9192
bool selective = false);
9293
bool sendMessageWithInlineKeyboard(const String& chat_id, const String& text,
93-
const String& parse_mode, const String& keyboard);
94+
const String& parse_mode, const String& keyboard, int message_id = 0);
9495

9596
bool sendChatAction(const String& chat_id, const String& text);
9697

97-
bool sendPostMessage(JsonObject payload);
98+
bool sendPostMessage(JsonObject payload, bool edit = false);
9899
String sendPostPhoto(JsonObject payload);
99100
String sendPhotoByBinary(const String& chat_id, const String& contentType, int fileSize,
100101
MoreDataAvailable moreDataAvailableCallback,

0 commit comments

Comments
 (0)