cotestatnt / AsyncTelegram2

Powerful, flexible and secure Arduino Telegram BOT library. Hardware independent, it can be used with any MCU capable of handling an SSL connection.
MIT License
83 stars 25 forks source link

What is the maximum Inline Keyboard buttons can we use? #69

Closed Dcmwrnd closed 2 years ago

Dcmwrnd commented 2 years ago

Hi Owner,

I added a total of 17 inline keyboard buttons but it only show 14 buttons on Telegram. What is the maximum inline keyboard buttons can we use? Example sketch is below here.

The other issue is I get repeated message from Telegram occasionally, not all the time. As I tap on the same inline keyboard button once, I can see from my terminal screen print out the same message twice occasionally. I did not double tap on the button. Tap once & waited for Telegram reply & sometimes the ESP32 will send out the button message twice. This is like a switch debounce kind of stuff, press once & get multiple pulse. Any solution to this? Thanks.


/*
  Name:        keyboards.ino
  Created:     05/03/2022
  Author:      Tolentino Cotesta <cotestatnt@yahoo.com>
  Description: a more complex example that do:
             1) if a "/inline_keyboard" text message is received, show the inline custom keyboard,
                if a "/reply_keyboard" text message is received, show the reply custom keyboard,
                otherwise reply the sender with "Try /reply_keyboard or /inline_keyboard" message
             2) if "LIGHT ON" inline keyboard button is pressed turn on the LED and show a message
             3) if "LIGHT OFF" inline keyboard button is pressed, turn off the LED and show a message
             4) if "GitHub" inline keyboard button is pressed,
                open a browser window with URL "https://github.com/cotestatnt/AsyncTelegram"

  Compile with:-
  Arduino IDE:     v1.8.19
  ArduinoJson:     v6.19.3
  Board Manager:   v1.0.6
  AsyncTelegram2:  v2.1.1
*/

#include <AsyncTelegram2.h>

// Timezone definition
#include <time.h>
#define MYTZ "CET-1CEST,M3.5.0,M10.5.0/3"

/*
  Set true if you want use external library for SSL connection 
  For example https://github.com/OPEnSLab-OSU/SSLClient/ is very efficient BearSSL library and 
  you can use AsyncTelegram2 even with other MCUs or transport layer (ex. Ethernet or GPRS)
*/
#define USE_CLIENTSSL false

#include <WiFi.h>
#include <WiFiClient.h>

#if USE_CLIENTSSL
    #include <SSLClient.h>      // https://github.com/OPEnSLab-OSU/SSLClient/
    #include "tg_certificate.h"
    WiFiClient base_client;
    SSLClient client(base_client, TAs, (size_t)TAs_NUM, A0, 1, SSLClient::SSL_ERROR);
  #else
    #include <WiFiClientSecure.h>
    WiFiClientSecure client;
#endif

AsyncTelegram2 myBot(client);

const char* ssid  =  "xxxxxxxxx";     // SSID WiFi network
const char* pass  =  "xxxxxxxxx";     // Password  WiFi network
const char* token =  "xxxxxxxxxxxx";  // Telegram token

// Check the userid with the help of bot @JsonDumpBot or @getidsbot (work also with groups)
// https://t.me/JsonDumpBot  or  https://t.me/getidsbot

int64_t userid = 123456789;

ReplyKeyboard myReplyKbd;   // reply keyboard object helper
InlineKeyboard myInlineKbd; // inline keyboard object helper
bool isKeyboardActive;      // store if the reply keyboard is shown

#define LIGHT_ON1_CALLBACK  "light 1 ON"  // Callback data sent when "LIGHT ON" button is pressed
#define LIGHT_OFF1_CALLBACK "light 1 OFF" // Callback data sent when "LIGHT OFF" button is pressed
#define LIGHT_ON2_CALLBACK  "light 2 ON"
#define LIGHT_OFF2_CALLBACK "light 2 OFF"
#define LIGHT_ON3_CALLBACK  "light 3 ON"
#define LIGHT_OFF3_CALLBACK "light 3 OFF"
#define LIGHT_ON4_CALLBACK  "light 4 ON"
#define LIGHT_OFF4_CALLBACK "light 4 OFF"
#define LIGHT_ON5_CALLBACK  "light 5 ON"
#define LIGHT_OFF5_CALLBACK "light 5 OFF"
#define LIGHT_ON6_CALLBACK  "light 6 ON"
#define LIGHT_OFF6_CALLBACK "light 6 OFF"

#define LIGHT_ON7_CALLBACK  "light 7 ON"
#define LIGHT_OFF7_CALLBACK "light 7 OFF"
#define LIGHT_ON8_CALLBACK  "light 8 ON"
#define LIGHT_OFF8_CALLBACK "light 8 OFF"

const uint8_t LED = 4;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(LED, OUTPUT);
  // initialize the Serial
  Serial.begin(115200);
  delay(180);

  // connects to the access point
  WiFi.begin(ssid, pass);
  delay(500);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(500);
  }

// Sync time with NTP
  configTzTime(MYTZ, "time.google.com", "time.windows.com", "pool.ntp.org");

#if USE_CLIENTSSL == false
    client.setCACert(telegram_cert);
#endif

  // Set the Telegram bot properties
  myBot.setUpdateTime(1000);
  myBot.setTelegramToken(token);

  // Check if all things are ok
  Serial.print("Test Telegram connection... ");
  myBot.begin() ? Serial.println("OK") : Serial.println("NOK");
  Serial.print("Bot name: @");
  Serial.println(myBot.getBotName());

  // Add reply keyboard
  isKeyboardActive = false;
  // add a button that send a message with "Simple button" text
  myReplyKbd.addButton("Button1");
  myReplyKbd.addButton("Button2");
  myReplyKbd.addButton("Button3");
  // add a new empty button row
  myReplyKbd.addRow();
  // add another button that send the user position (location)
  myReplyKbd.addButton("Send Location", KeyboardButtonLocation);
  // add another button that send the user contact
  myReplyKbd.addButton("Send contact", KeyboardButtonContact);
  // add a new empty button row
  myReplyKbd.addRow();
  // add a button that send a message with "Hide replyKeyboard" text
  // (it will be used to hide the reply keyboard)
  myReplyKbd.addButton("/hide_keyboard");
  // resize the keyboard to fit only the needed space
  myReplyKbd.enableResize();

// Add sample inline keyboard
  myInlineKbd.addButton("ON 1", LIGHT_ON1_CALLBACK, KeyboardButtonQuery);
  myInlineKbd.addButton("OFF 1", LIGHT_OFF1_CALLBACK, KeyboardButtonQuery);
  myInlineKbd.addButton("ON 2", LIGHT_ON2_CALLBACK, KeyboardButtonQuery);
  myInlineKbd.addButton("OFF 2", LIGHT_OFF2_CALLBACK, KeyboardButtonQuery);
  myInlineKbd.addRow();
  myInlineKbd.addButton("ON 3", LIGHT_ON3_CALLBACK, KeyboardButtonQuery);
  myInlineKbd.addButton("OFF 3", LIGHT_OFF3_CALLBACK, KeyboardButtonQuery);
  myInlineKbd.addButton("ON 4", LIGHT_ON4_CALLBACK, KeyboardButtonQuery);
  myInlineKbd.addButton("OFF 4", LIGHT_OFF4_CALLBACK, KeyboardButtonQuery);
  myInlineKbd.addRow();
  myInlineKbd.addButton("ON 5", LIGHT_ON5_CALLBACK, KeyboardButtonQuery);
  myInlineKbd.addButton("OFF 5", LIGHT_OFF5_CALLBACK, KeyboardButtonQuery);
  myInlineKbd.addButton("ON 6", LIGHT_ON6_CALLBACK, KeyboardButtonQuery);
  myInlineKbd.addButton("OFF 6", LIGHT_OFF6_CALLBACK, KeyboardButtonQuery);
  myInlineKbd.addRow();

  myInlineKbd.addButton("ON 7", LIGHT_ON7_CALLBACK, KeyboardButtonQuery);
  myInlineKbd.addButton("OFF 7", LIGHT_OFF7_CALLBACK, KeyboardButtonQuery);
  myInlineKbd.addButton("ON 8", LIGHT_ON8_CALLBACK, KeyboardButtonQuery);
  myInlineKbd.addButton("OFF 8", LIGHT_OFF8_CALLBACK, KeyboardButtonQuery);
  myInlineKbd.addRow();

  myInlineKbd.addButton("GitHub", "https://github.com/cotestatnt/AsyncTelegram2/", KeyboardButtonURL);

  char welcome_msg[128];
  snprintf(welcome_msg, 128, "BOT @%s online\n/help all commands avalaible.", myBot.getBotName());

  // Send a message to specific user who has started your bot
  myBot.sendTo(userid, welcome_msg);
}

void loop() {

  // In the meantime LED_BUILTIN will blink with a fixed frequency
  // to evaluate async and non-blocking working of library
  static uint32_t ledTime = millis();
  if (millis() - ledTime > 200) {
    ledTime = millis();
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  }

  // if there is an incoming message...
  // local variable to store telegram message data
  TBMessage msg;
  if (myBot.getNewMessage(msg)) {
    // check what kind of message I received
    MessageType msgType = msg.messageType;
    String msgText = msg.text;

    switch (msgType) {
      case MessageText :
        // received a text message
        Serial.print("\nText message received: ");
        Serial.println(msgText);

        // check if is show keyboard command
        if (msgText.equalsIgnoreCase("/reply_keyboard")) {
          // the user is asking to show the reply keyboard --> show it
          myBot.sendMessage(msg, "This is reply keyboard:", myReplyKbd);
          isKeyboardActive = true;
        }
        else if (msgText.equalsIgnoreCase("/inline_keyboard")) {
          myBot.sendMessage(msg, "This is inline keyboard:", myInlineKbd);
        }

        // check if the reply keyboard is active
        else if (isKeyboardActive) {
          // is active -> manage the text messages sent by pressing the reply keyboard buttons
          if (msgText.equalsIgnoreCase("/hide_keyboard")) {
            // sent the "hide keyboard" message --> hide the reply keyboard
            myBot.removeReplyKeyboard(msg, "Reply keyboard removed");
            isKeyboardActive = false;
          } else {
            // print every others messages received

            myBot.sendMessage(msg, msg.text);
//            sendRxMsg();

          }
        }

        // the user write anything else and the reply keyboard is not active --> show a hint message
        else {
          myBot.sendMessage(msg, "Try /reply_keyboard or /inline_keyboard");
        }
        break;

      case MessageQuery:

        // received a callback query message
        msgText = msg.callbackQueryData;

        Serial.print("\nCallback query message received: ");
        Serial.println(msg.callbackQueryData);

        if (msgText.equalsIgnoreCase(LIGHT_ON1_CALLBACK)) {
          // Pushed "LIGHT ON" button...
          Serial.println("\nSet light 1 ON");
          digitalWrite(LED, HIGH);
          // Terminate the callback with an alert message
          myBot.endQuery(msg, "Light 1 on", true);
        }
        else if (msgText.equalsIgnoreCase(LIGHT_OFF1_CALLBACK)) {
          // Pushed "LIGHT OFF" button...
          Serial.println("\nSet light 1 OFF");
          digitalWrite(LED, LOW);
          // Terminate the callback with a popup message
          myBot.endQuery(msg, "Light 1 off");
        }

        if (msgText.equalsIgnoreCase(LIGHT_ON2_CALLBACK)) {
          Serial.println("\nSet light 2 ON");
          digitalWrite(LED, HIGH);
          myBot.endQuery(msg, "Light 2 on", true);
        }
        else if (msgText.equalsIgnoreCase(LIGHT_OFF2_CALLBACK)) {
          Serial.println("\nSet light 2 OFF");
          digitalWrite(LED, LOW);
          myBot.endQuery(msg, "Light 2 off");
        }

        if (msgText.equalsIgnoreCase(LIGHT_ON3_CALLBACK)) {
          Serial.println("\nSet light 3 ON");
          digitalWrite(LED, HIGH);
          myBot.endQuery(msg, "Light 3 on", true);
        }
        else if (msgText.equalsIgnoreCase(LIGHT_OFF3_CALLBACK)) {
          Serial.println("\nSet light 3 OFF");
          digitalWrite(LED, LOW);
          myBot.endQuery(msg, "Light 3 off");
        }

        if (msgText.equalsIgnoreCase(LIGHT_ON4_CALLBACK)) {
          Serial.println("\nSet light 4 ON");
          digitalWrite(LED, HIGH);
          myBot.endQuery(msg, "Light 4 on", true);
        }
        else if (msgText.equalsIgnoreCase(LIGHT_OFF4_CALLBACK)) {
          Serial.println("\nSet light 4 OFF");
          digitalWrite(LED, LOW);
          myBot.endQuery(msg, "Light 4 off");
        }

        if (msgText.equalsIgnoreCase(LIGHT_ON5_CALLBACK)) {
          Serial.println("\nSet light 5 ON");
          digitalWrite(LED, HIGH);
          myBot.endQuery(msg, "Light 5 on", true);
        }
        else if (msgText.equalsIgnoreCase(LIGHT_OFF5_CALLBACK)) {
          Serial.println("\nSet light 5 OFF");
          digitalWrite(LED, LOW);
          myBot.endQuery(msg, "Light 5 off");
        }

        if (msgText.equalsIgnoreCase(LIGHT_ON6_CALLBACK)) {
          Serial.println("\nSet light 6 ON");
          digitalWrite(LED, HIGH);
          myBot.endQuery(msg, "Light 6 on", true);
        }
        else if (msgText.equalsIgnoreCase(LIGHT_OFF6_CALLBACK)) {
          Serial.println("\nSet light 6 OFF");
          digitalWrite(LED, LOW);
          myBot.endQuery(msg, "Light 6 off");
        }

        if (msgText.equalsIgnoreCase(LIGHT_ON7_CALLBACK)) {
          Serial.println("\nSet light 7 ON");
          digitalWrite(LED, HIGH);
          myBot.endQuery(msg, "Light 7 on", true);
        }
        else if (msgText.equalsIgnoreCase(LIGHT_OFF7_CALLBACK)) {
          Serial.println("\nSet light 7 OFF");
          digitalWrite(LED, LOW);
          myBot.endQuery(msg, "Light 7 off");
        }

        if (msgText.equalsIgnoreCase(LIGHT_ON8_CALLBACK)) {
          Serial.println("\nSet light 8 ON");
          digitalWrite(LED, HIGH);
          myBot.endQuery(msg, "Light 8 on", true);
        }
        else if (msgText.equalsIgnoreCase(LIGHT_OFF8_CALLBACK)) {
          Serial.println("\nSet light 8 OFF");
          digitalWrite(LED, LOW);
          myBot.endQuery(msg, "Light 8 off");
        }

        break;

      case MessageLocation: {
          // received a location message
          String reply = "Longitude: ";
          reply += msg.location.longitude;
          reply += "; Latitude: ";
          reply += msg.location.latitude;
          Serial.println(reply);
          myBot.sendMessage(msg, reply);
          break;
        }

      case MessageContact: {
          // received a contact message
          String reply = "Contact information received:";
          reply += msg.contact.firstName;
          reply += " ";
          reply += msg.contact.lastName;
          reply += ", mobile ";
          reply += msg.contact.phoneNumber;
          Serial.println(reply);
          myBot.sendMessage(msg, reply);
          break;
        }

      default:
        break;
    }
  }
}
Dcmwrnd commented 2 years ago

Hi Owner,

If you replace this 'case MessageQuery:' below on the example sketch and you tap on any of the 2 difference 'ON' button within 1 or 2 seconds in between, you will see repeated message.

```

case MessageQuery:

    // received a callback query message
    msgText = msg.callbackQueryData;

    Serial.print("\nCallback query message received: ");
    Serial.println(msg.callbackQueryData);

    if (msgText.equalsIgnoreCase(LIGHT_ON1_CALLBACK)) {
      // Pushed "LIGHT ON" button...
      Serial.println("\nSet light 1 ON");
      digitalWrite(LED, HIGH);
      // Terminate the callback with an alert message

// myBot.endQuery(msg, "Light 1 on", true); myBot.sendMessage(msg, "Light 1 on"); delay(2000); digitalWrite(LED, LOW); myBot.sendMessage(msg, "Light 1 oFF");
}

    else if (msgText.equalsIgnoreCase(LIGHT_OFF1_CALLBACK)) {
      // Pushed "LIGHT OFF" button...
      Serial.println("\nSet light 1 OFF");
      digitalWrite(LED, LOW);
      // Terminate the callback with a popup message

// myBot.endQuery(msg, "Light 1 off"); myBot.sendMessage(msg, "Light 1 oFF"); }

    if (msgText.equalsIgnoreCase(LIGHT_ON2_CALLBACK)) {
      Serial.println("\nSet light 2 ON");
      digitalWrite(LED, HIGH);

// myBot.endQuery(msg, "Light 2 on", true); myBot.sendMessage(msg, "Light 2 on"); delay(2500); digitalWrite(LED, LOW); myBot.sendMessage(msg, "Light 2 oFF"); }

    else if (msgText.equalsIgnoreCase(LIGHT_OFF2_CALLBACK)) {
      Serial.println("\nSet light 2 OFF");
      digitalWrite(LED, LOW);

// myBot.endQuery(msg, "Light 2 off"); myBot.sendMessage(msg, "Light 2 off"); }

    if (msgText.equalsIgnoreCase(LIGHT_ON3_CALLBACK)) {
      Serial.println("\nSet light 3 ON");
      digitalWrite(LED, HIGH);

// myBot.endQuery(msg, "Light 3 on", true); myBot.sendMessage(msg, "Light 3 on"); delay(3000); digitalWrite(LED, LOW); myBot.sendMessage(msg, "Light 3 oFF"); }

    else if (msgText.equalsIgnoreCase(LIGHT_OFF3_CALLBACK)) {
      Serial.println("\nSet light 3 OFF");
      digitalWrite(LED, LOW);

// myBot.endQuery(msg, "Light 3 off"); myBot.sendMessage(msg, "Light 3 off"); }

    if (msgText.equalsIgnoreCase(LIGHT_ON4_CALLBACK)) {
      Serial.println("\nSet light 4 ON");
      digitalWrite(LED, HIGH);

// myBot.endQuery(msg, "Light 4 on", true); myBot.sendMessage(msg, "Light 4 on"); delay(1800); digitalWrite(LED, LOW); myBot.sendMessage(msg, "Light 4 oFF"); }

    else if (msgText.equalsIgnoreCase(LIGHT_OFF4_CALLBACK)) {
      Serial.println("\nSet light 4 OFF");
      digitalWrite(LED, LOW);

// myBot.endQuery(msg, "Light 4 off"); myBot.sendMessage(msg, "Light 4 off"); }

    if (msgText.equalsIgnoreCase(LIGHT_ON5_CALLBACK)) {
      Serial.println("\nSet light 5 ON");
      digitalWrite(LED, HIGH);

// myBot.endQuery(msg, "Light 5 on", true); myBot.sendMessage(msg, "Light 5 on"); delay(2700); digitalWrite(LED, LOW); myBot.sendMessage(msg, "Light 5 oFF"); }

    else if (msgText.equalsIgnoreCase(LIGHT_OFF5_CALLBACK)) {
      Serial.println("\nSet light 5 OFF");
      digitalWrite(LED, LOW);

// myBot.endQuery(msg, "Light 5 off"); myBot.sendMessage(msg, "Light 5 off"); }

    if (msgText.equalsIgnoreCase(LIGHT_ON6_CALLBACK)) {
      Serial.println("\nSet light 6 ON");
      digitalWrite(LED, HIGH);

// myBot.endQuery(msg, "Light 6 on", true); myBot.sendMessage(msg, "Light 6 on"); delay(2000); digitalWrite(LED, LOW); myBot.sendMessage(msg, "Light 6 oFF"); }

    else if (msgText.equalsIgnoreCase(LIGHT_OFF6_CALLBACK)) {
      Serial.println("\nSet light 6 OFF");
      digitalWrite(LED, LOW);

// myBot.endQuery(msg, "Light 6 off"); myBot.sendMessage(msg, "Light 6 off"); }

    if (msgText.equalsIgnoreCase(LIGHT_ON7_CALLBACK)) {
      Serial.println("\nSet light 7 ON");
      digitalWrite(LED, HIGH);

// myBot.endQuery(msg, "Light 7 on", true); myBot.sendMessage(msg, "Light 7 on"); delay(1000); digitalWrite(LED, LOW); myBot.sendMessage(msg, "Light 7 oFF"); }

    else if (msgText.equalsIgnoreCase(LIGHT_OFF7_CALLBACK)) {
      Serial.println("\nSet light 7 OFF");
      digitalWrite(LED, LOW);

// myBot.endQuery(msg, "Light 7 off"); myBot.sendMessage(msg, "Light 7 off"); }

    if (msgText.equalsIgnoreCase(LIGHT_ON8_CALLBACK)) {
      Serial.println("\nSet light 8 ON");
      digitalWrite(LED, HIGH);

// myBot.endQuery(msg, "Light 8 on", true); myBot.sendMessage(msg, "Light 8 on"); delay(1200); digitalWrite(LED, LOW); myBot.sendMessage(msg, "Light 8 oFF"); }

    else if (msgText.equalsIgnoreCase(LIGHT_OFF8_CALLBACK)) {
      Serial.println("\nSet light 8 OFF");
      digitalWrite(LED, LOW);

// myBot.endQuery(msg, "Light 8 off"); myBot.sendMessage(msg, "Light 8 off"); }

    break;
cotestatnt commented 2 years ago

Hi @Dcmwrnd The only limit should be the available memory as the buttons are dynamically allocated, but in fact I have tried your sketch and it doesn't work as you write. The buffer used to prepare the message is probably not large enough. I need to investigate more thoroughly.

Regarding your second question, a MessageQuery message need to be "ended" with a endQuery command and it remains cached for some seconds from telegram server.

Dcmwrnd commented 2 years ago

Hi Cotestatnt,

In fact I migrated this sketch from the old UniversalTelegramBot & was working as it is but a bit slow in respond.

With regards to my second question, even if I moved out from the ‘case MessageQuery:’ using ‘myBot.sendMessage(msg, "Light 8 off");’ or ‘myBot.sendTo(userid, " Light 8 off ");’ by pressing a few inline keyboard buttons will also get repeated message from Telegram. The strange thing is this repeated message come in occasionally, not all the time. I suppose Telegram server will delete the last message instantly once they acknowledged it. Maybe the ESP32 running async is too fast for Telegram to coup with. Meantime I will put some delay in between & see what happen.

cotestatnt commented 2 years ago

The missing buttons are due to the size of this JSON buffer. If you increase from BUFFER_MEDIUM to BUFFER_BIG it should work as you expect. I'm sorry but I have really a few free time in this period, I will increase max size "officially" in the next release.

Anyway when you have a such "static" inline keybaord, it's better to use a const char* string keyboard instead create it at runtime in order to increase performance and use in a better way avalaible SRAM.

const char* myInlineKbd PROGMEM = 
  "{\"inline_keyboard\":["
  "[{\"text\":\"ON1\",\"callback_data\":\"light1ON\"},"
  "{\"text\":\"OFF1\",\"callback_data\":\"light1OFF\"},"
  "{\"text\":\"ON2\",\"callback_data\":\"light2ON\"},"
  "{\"text\":\"OFF2\",\"callback_data\":\"light2OFF\"}],"  /* First row */
  "[{\"text\":\"ON3\",\"callback_data\":\"light3ON\"},"
  "{\"text\":\"OFF3\",\"callback_data\":\"light3OFF\"},"
  "{\"text\":\"ON4\",\"callback_data\":\"light4ON\"},"
  "{\"text\":\"OFF4\",\"callback_data\":\"light4OFF\"}],"  /* Second row */
  "[{\"text\":\"ON5\",\"callback_data\":\"light5ON\"},"
  "{\"text\":\"OFF5\",\"callback_data\":\"light5OFF\"},"
  "{\"text\":\"ON6\",\"callback_data\":\"light6ON\"},"
  "{\"text\":\"OFF6\",\"callback_data\":\"light6OFF\"}],"   /* Third row */
  "[{\"text\":\"ON7\",\"callback_data\":\"light7ON\"},"
  "{\"text\":\"OFF7\",\"callback_data\":\"light7OFF\"},"
  "{\"text\":\"ON8\",\"callback_data\":\"light8ON\"},"
  "{\"text\":\"OFF8\",\"callback_data\":\"light8OFF\"}]"    /* Last row */
  "]}";

Regarding the repeated message try sending soon the endQuery command and only after parse the message. Keep in mind that callback query message will be cached from Telegram server, actually it is set to 5 second but if you need you can decrese that time in this line of code editing the value of cache_time

    ......
    case MessageQuery:
      // received a callback query message
      msgText = msg.callbackQueryData;
      Serial.print("\nCallback query message received: ");
      Serial.println(msg.callbackQueryData);
      myBot.endQuery(msg, "OK", false);

      // Parse received callback message text
      .....
Dcmwrnd commented 2 years ago

Hi Cotestatnt,

After inserting this line.. myBot.endQuery(msg, "OK", false); in the ‘case MessageQuery:’ Voila!.. it seems working perfectly now, no more repeated message. I did not alter the cache_time, still maintain at 5 seconds.

Json buffer increased from MEDIUM to BIG and using ‘const char* myInlineKbd PROGMEM’ Again, voila!.. all the buttons show up. After increased to BIG, I also tested with myInlineKbd.addButton() but the buttons did not show up fully.

Both problems solved. Thank you very much for your time & effort.