//+------------------------------------------------------------------+ //| ReplyMarkup.mqh | //| Copyright 2026, Niquel Mendoza. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2026, Niquel Mendoza." #property link "https://www.mql5.com" #property strict #ifndef TELEGRAMBYLEO_SRC_BOTTONS_REPLYMARKUP_MQH #define TELEGRAMBYLEO_SRC_BOTTONS_REPLYMARKUP_MQH //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #include "KeyboardBase.mqh" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ namespace TSN { //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ //---- #define TLGBYLEO_RK_OFF_IS_PERSISTENT_KEY 0 #define TLGBYLEO_RK_LEN_IS_PERSISTENT_KEY 16 #define TLGBYLEO_RK_OFF_RESIZE_KEYBOARD_KEY 16 #define TLGBYLEO_RK_LEN_RESIZE_KEYBOARD_KEY 18 #define TLGBYLEO_RK_OFF_ONE_TIME_KEYBOARD_KEY 34 #define TLGBYLEO_RK_LEN_ONE_TIME_KEYBOARD_KEY 20 #define TLGBYLEO_RK_OFF_INPUT_FIELD_PLACEHOLDER_KEY 54 #define TLGBYLEO_RK_LEN_INPUT_FIELD_PLACEHOLDER_KEY 27 #define TLGBYLEO_RK_OFF_SELECTIVE_KEY 81 #define TLGBYLEO_RK_LEN_SELECTIVE_KEY 12 #define TLGBYLEO_RK_OFF_FORCE_REPLY_KEY 93 #define TLGBYLEO_RK_LEN_FORCE_REPLY_KEY 14 #define TLGBYLEO_RK_OFF_KEYBOARD_ARR_KEY 107 #define TLGBYLEO_RK_LEN_KEYBOARD_ARR_KEY 12 #define TLGBYLEO_RK_OFF_TRUE_LIT 119 #define TLGBYLEO_RK_LEN_TRUE_LIT 4 #define TLGBYLEO_RK_OFF_FALSE_LIT 123 #define TLGBYLEO_RK_LEN_FALSE_LIT 5 //---- const uchar g_tlgreplykeyboard_texts[] = { '"', 'i', 's', '_', 'p', 'e', 'r', 's', 'i', 's', 't', 'e', 'n', 't', '"', ':', // [0..15] IS_PERSISTENT_KEY: "is_persistent": '"', 'r', 'e', 's', 'i', 'z', 'e', '_', 'k', 'e', 'y', 'b', 'o', 'a', 'r', 'd', '"', ':', // [16..33] RESIZE_KEYBOARD_KEY: "resize_keyboard": '"', 'o', 'n', 'e', '_', 't', 'i', 'm', 'e', '_', 'k', 'e', 'y', 'b', 'o', 'a', 'r', 'd', '"', ':', // [34..53] ONE_TIME_KEYBOARD_KEY: "one_time_keyboard": '"', 'i', 'n', 'p', 'u', 't', '_', 'f', 'i', 'e', 'l', 'd', '_', 'p', 'l', 'a', 'c', 'e', 'h', 'o', 'l', 'd', 'e', 'r', '"', ':', '"', // [54..80] INPUT_FIELD_PLACEHOLDER_KEY: "input_field_placeholder":" '"', 's', 'e', 'l', 'e', 'c', 't', 'i', 'v', 'e', '"', ':', // [81..92] SELECTIVE_KEY: "selective": '"', 'f', 'o', 'r', 'c', 'e', '_', 'r', 'e', 'p', 'l', 'y', '"', ':', // [93..106] FORCE_REPLY_KEY: "force_reply": '"', 'k', 'e', 'y', 'b', 'o', 'a', 'r', 'd', '"', ':', '[', // [107..118] KEYBOARD_ARR_KEY: "keyboard":[ 't', 'r', 'u', 'e', // [119..122] TRUE_LIT 'f', 'a', 'l', 's', 'e' // [123..127] FALSE_LIT }; //--- const uchar g_tlgreplykeyboard_remove[] = { //--- '{', '"', 'r', 'e', 'm', 'o', 'v', 'e', '_', 'k', 'e', 'y', 'b', 'o', 'a', 'r', 'd', '"', ':', 't', 'r', 'u', 'e', '}' }; //--- #define TLGBYLEO_RK_BOOL_FIELD(off, len, value) \ if(m_has_field) \ m_buf[m_pos++] = ','; \ m_pos += ArrayCopy(m_buf, g_tlgreplykeyboard_texts, m_pos, off, len); \ if(value) \ m_pos += ArrayCopy(m_buf, g_tlgreplykeyboard_texts, m_pos, TLGBYLEO_RK_OFF_TRUE_LIT, TLGBYLEO_RK_LEN_TRUE_LIT); \ else \ m_pos += ArrayCopy(m_buf, g_tlgreplykeyboard_texts, m_pos, TLGBYLEO_RK_OFF_FALSE_LIT, TLGBYLEO_RK_LEN_FALSE_LIT); \ m_has_field = true; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CTlgReplyKeyboard : public CTlgKeyboardBase { private: //--- bool m_has_field; public: CTlgReplyKeyboard(uint initial_cap = 256); ~CTlgReplyKeyboard(void) {} //--- __forceinline void Clear() { m_pos = 0; m_in_row = false; m_in_boton = false; m_has_field = false; } void Init(); void InitArr(); void Finish(); //--- config (nivel objeto, antes de InitArr()) CTlgReplyKeyboard* IsPersistent(bool value); CTlgReplyKeyboard* ResizeKeyboard(bool value); CTlgReplyKeyboard* OneTimeKeyboard(bool value); CTlgReplyKeyboard* InputFieldPlaceholder(const string& text); CTlgReplyKeyboard* InputFieldPlaceholder(const CStringFixed& text); CTlgReplyKeyboard* Selective(bool value); CTlgReplyKeyboard* ForceReply(bool value); //--- filas / botones __forceinline CTlgReplyKeyboard* AddRow() { AddRowImpl(); return &this; } __forceinline CTlgReplyKeyboard* EndRow() { EndRowImpl(); return &this; } CTlgReplyKeyboard* AddBtn(const string& text); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CTlgReplyKeyboard::CTlgReplyKeyboard(uint initial_cap = 256) : CTlgKeyboardBase(initial_cap), m_has_field(false) { } //+------------------------------------------------------------------+ void CTlgReplyKeyboard::Init(void) { //--- m_pos = 0; m_in_row = false; m_in_boton = false; m_has_field = false; //--- { TLGBYLEO_KEYBORAD_RESERVE(1) m_buf[m_pos++] = '{'; } //+------------------------------------------------------------------+ void CTlgReplyKeyboard::Finish(void) { TLGBYLEO_KEYBORAD_RESERVE(2) m_buf[m_pos++] = ']'; m_buf[m_pos++] = '}'; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CTlgReplyKeyboard* CTlgReplyKeyboard::IsPersistent(bool value) { TLGBYLEO_KEYBORAD_RESERVE(TLGBYLEO_RK_LEN_IS_PERSISTENT_KEY + 6) TLGBYLEO_RK_BOOL_FIELD(TLGBYLEO_RK_OFF_IS_PERSISTENT_KEY, TLGBYLEO_RK_LEN_IS_PERSISTENT_KEY, value) return &this; } //+------------------------------------------------------------------+ CTlgReplyKeyboard* CTlgReplyKeyboard::ResizeKeyboard(bool value) { TLGBYLEO_KEYBORAD_RESERVE(TLGBYLEO_RK_LEN_RESIZE_KEYBOARD_KEY + 6) TLGBYLEO_RK_BOOL_FIELD(TLGBYLEO_RK_OFF_RESIZE_KEYBOARD_KEY, TLGBYLEO_RK_LEN_RESIZE_KEYBOARD_KEY, value) return &this; } //+------------------------------------------------------------------+ CTlgReplyKeyboard* CTlgReplyKeyboard::OneTimeKeyboard(bool value) { TLGBYLEO_KEYBORAD_RESERVE(TLGBYLEO_RK_LEN_ONE_TIME_KEYBOARD_KEY + 6) TLGBYLEO_RK_BOOL_FIELD(TLGBYLEO_RK_OFF_ONE_TIME_KEYBOARD_KEY, TLGBYLEO_RK_LEN_ONE_TIME_KEYBOARD_KEY, value) return &this; } //+------------------------------------------------------------------+ CTlgReplyKeyboard* CTlgReplyKeyboard::Selective(bool value) { TLGBYLEO_KEYBORAD_RESERVE(TLGBYLEO_RK_LEN_SELECTIVE_KEY + 6) TLGBYLEO_RK_BOOL_FIELD(TLGBYLEO_RK_OFF_SELECTIVE_KEY, TLGBYLEO_RK_LEN_SELECTIVE_KEY, value) return &this; } //+------------------------------------------------------------------+ CTlgReplyKeyboard* CTlgReplyKeyboard::ForceReply(bool value) { TLGBYLEO_KEYBORAD_RESERVE(TLGBYLEO_RK_LEN_FORCE_REPLY_KEY + 6) TLGBYLEO_RK_BOOL_FIELD(TLGBYLEO_RK_OFF_FORCE_REPLY_KEY, TLGBYLEO_RK_LEN_FORCE_REPLY_KEY, value) return &this; } //+------------------------------------------------------------------+ CTlgReplyKeyboard* CTlgReplyKeyboard::InputFieldPlaceholder(const string &text) { //--- const int len = StringLen(text); const int req = (len * 6) + TLGBYLEO_RK_LEN_INPUT_FIELD_PLACEHOLDER_KEY + 2; TLGBYLEO_KEYBORAD_RESERVE(req) //--- if(m_has_field) m_buf[m_pos++] = ','; m_pos += ArrayCopy(m_buf, g_tlgreplykeyboard_texts, m_pos, TLGBYLEO_RK_OFF_INPUT_FIELD_PLACEHOLDER_KEY, TLGBYLEO_RK_LEN_INPUT_FIELD_PLACEHOLDER_KEY); CJsonEscape::Encode(text, len, m_buf, m_pos); m_buf[m_pos++] = '"'; m_has_field = true; //--- return &this; } //+------------------------------------------------------------------+ CTlgReplyKeyboard* CTlgReplyKeyboard::InputFieldPlaceholder(const CStringFixed &text) { //--- const int req = TLGBYLEO_RK_LEN_INPUT_FIELD_PLACEHOLDER_KEY + text.len + 2; TLGBYLEO_KEYBORAD_RESERVE(req) //--- if(m_has_field) m_buf[m_pos++] = ','; m_pos += ArrayCopy(m_buf, g_tlgreplykeyboard_texts, m_pos, TLGBYLEO_RK_OFF_INPUT_FIELD_PLACEHOLDER_KEY, TLGBYLEO_RK_LEN_INPUT_FIELD_PLACEHOLDER_KEY); m_pos += ArrayCopy(m_buf, text.raw, m_pos, 0, text.len); m_buf[m_pos++] = '"'; m_has_field = true; //--- return &this; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTlgReplyKeyboard::InitArr(void) { //--- ,"keyboard":[ (coma solo si ya se escribio algun campo antes) TLGBYLEO_KEYBORAD_RESERVE(TLGBYLEO_RK_LEN_KEYBOARD_ARR_KEY + 1) if(m_has_field) m_buf[m_pos++] = ','; m_pos += ArrayCopy(m_buf, g_tlgreplykeyboard_texts, m_pos, TLGBYLEO_RK_OFF_KEYBOARD_ARR_KEY, TLGBYLEO_RK_LEN_KEYBOARD_ARR_KEY); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CTlgReplyKeyboard* CTlgReplyKeyboard::AddBtn(const string &text) { //--- const int len = StringLen(text); const int req = (len * 6) + 4; TLGBYLEO_KEYBORAD_RESERVE(req) //--- coma si ya hay un boton antes en esta fila if(m_in_boton) m_buf[m_pos++] = ','; //--- m_buf[m_pos++] = '"'; CJsonEscape::Encode(text, len, m_buf, m_pos); m_buf[m_pos++] = '"'; m_in_boton = true; //--- return &this; } } //+------------------------------------------------------------------+ #endif // TELEGRAMBYLEO_SRC_BOTTONS_REPLYMARKUP_MQH