//+------------------------------------------------------------------+ //| Misce.mq5 | //| Copyright 2026, Niquel Mendoza. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2026, Niquel Mendoza." #property link "https://www.mql5.com" #property version "1.00" #property strict #property description "Bot de pruebas para ver la funcionalidad de los comandos" //+------------------------------------------------------------------+ //| Include | //+------------------------------------------------------------------+ #include "..\\Src\\CommandsApi.mqh" #include "..\\Src\\Bottons\\Inline.mqh" #include "..\\Src\\Bottons\\ReplyMarkup.mqh" #include //+------------------------------------------------------------------+ //| Inputs | //+------------------------------------------------------------------+ input string InpBotToken = ""; input long InpBotChatId = 0; //+------------------------------------------------------------------+ //| Ejemplos basicos | //+------------------------------------------------------------------+ class CMyBot : public TSN::CTelegramCommandBot { private: //--- TSN::CTlgInlineKeyboard m_inline_bottons; TSN::CTlgReplyKeyboard m_keyboard; //--- void OnCommand(int command_idx, long chat_id, TSN::CJsonNode& json) override final { switch(command_idx) { case 0: // /start { SendMessage("Hola como estas?¿"); break; } case 1: // /poll { TSN::TlgInputPollOption ops[2]; ops[0].text = "La repuesta es 2"; ops[0].text_parse_mode = WRONG_VALUE; ops[1].text = "La respuesta es 4 xd"; ops[1].text_parse_mode = WRONG_VALUE; //--- SendPollQuiz("Cuanto es 1 + 1?", WRONG_VALUE, ops, TimeGMT() + 100, "La idea es ver qeu tan inteersante es esto?¿ eso creo no D:", WRONG_VALUE, TLGBYLEO_BOOL_TRUE, "La repuesta correcta es la opcion es 2 obviamente", WRONG_VALUE, 0); break; } case 2: // /reaction { const long v = json["message_id"].ToInt(0); TSN::TlgReactionType reac[1]; reac[0].type = TSN::TELEGRAMBYLEO_REACTION_TYPE_EMOJI; reac[0].value = "😐"; SetMessageReaction(v, TLGBYLEO_BOOL_TRUE, reac); break; } case 3: // foto { if(!ChartScreenShot(0, "Temp\\foto.png", 600, 300)) break; SendPhoto("Foto del grafico actual", WRONG_VALUE, "Temp\\foto.png", false); break; } case 4: // documento { TSN::CJsonNode text = json["text"]; TSN::CStringView view(text.StrStart(), text.StrLenRaw(), text.m_ctx); int pos = view.Find('['); if(pos == -1) { SendMessage("Se esperaba un [ de incio para el file"); break; } pos++; int end = view.Find(']', pos); if(end == -1) { SendMessage("Se espera un fin.. bueno con ]"); break; } const string path = view.SubtrStrRaw(pos, (end - pos)); SendChatAction(TSN::TELEGRAMBYLEO_CHAT_ACTION_UPLOAD_DOCUMENT); SendDocument("Archivo que me pediste que suba xd", WRONG_VALUE, path, false); break; } case 5: // XD { m_inline_bottons.Clear(); m_inline_bottons.Init(); m_inline_bottons.AddRow().AddBtnCallbackData("Balance", "id_balance").AddBtnCallbackData("Current price", "id_curr_price").EndRow(); m_inline_bottons.Finish(); //--- SendMessage("Hola aqui tus botones", WRONG_VALUE, EMPTY_TLG_SEND_BASE, EMPTY_TLG_REPLY_PARAMS, EMPTY_TLG_EPEMERAL, EMPTY_LINK_PREVIEW_OPS, m_inline_bottons.m_buf, m_inline_bottons.m_pos); break; } case 6: // All { m_keyboard.Clear(); m_keyboard.Init(); m_keyboard.OneTimeKeyboard(true); m_keyboard.InitArr(); m_keyboard.AddRow().AddBtn("/start").AddBtn("/reaction").AddBtn("/doc").EndRow(); m_keyboard.AddRow().AddBtn("/poll").AddBtn("/foto").AddBtn("/XD").EndRow(); m_keyboard.Finish(); //--- SendMessage("Aqui todos los comandos", WRONG_VALUE, EMPTY_TLG_SEND_BASE, EMPTY_TLG_REPLY_PARAMS, EMPTY_TLG_EPEMERAL, EMPTY_LINK_PREVIEW_OPS, m_keyboard.m_buf, m_keyboard.m_pos); break; } case 7: // RKeyboard { // USO de bajo nivel.. trabajsmo directo.. tambien se puede usar SendMessage pero habria que pasrle el buffer armado a mano o // declrar m_js_builder.ApplySnapshot(m_chat_id_snap); m_js_builder.KeyWV("text").ValSWV("Se quitaron todos los botones"); m_js_builder.KeyWV("reply_markup").ValidJson(TSN::g_tlgreplykeyboard_remove); m_js_builder.EndObj(); //--- Mandamos tal cual.. Send(TELEGRAMBYLEO_ENDPOINT_SENDMESSAGE, m_js_builder); break; } } } //--- void OnCallbackQuery(TSN::CJsonNode& json) override final { TSN::CJsonNode data = json["data"]; TSN::CStringView view(data.StrStart(), data.StrLenRaw(), data.m_ctx); const string id = json["id"].ToString(); //--- en este caso comparacion a mano... si lo deseas tambien hashmap por jemeplo mas idx.. depende... // o tambien reusar el hashmap base... si sabes que tus comadnos no empizas idmgoas con un preijo tipo id_... seira lo ideall.. // en este caso como son dos comandos asi noma xreo. if(view.CmpLex("id_balance") == 0) { AnswerCallbackQuery(id, StringFormat("Balance actual = %.2f", AccountInfoDouble(ACCOUNT_BALANCE)), ""); } else if(view.CmpLex("id_curr_price") == 0) { AnswerCallbackQuery(id, StringFormat("Precio actual = %.2f", SymbolInfoDouble(_Symbol, SYMBOL_BID)), ""); } } public: CMyBot() {} ~CMyBot() {} }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CMyBot g_bot; TSN::CTelegramBotUpdater g_tlg_bot_poller; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- g_tlg_bot_poller.Token(InpBotToken); g_tlg_bot_poller.RegisterEvent(&g_bot, TSN::TELEGRAMBYLEO_GETUPT_K_MESSAGE); g_tlg_bot_poller.RegisterEvent(&g_bot, TSN::TELEGRAMBYLEO_GETUPT_K_CALLBACK_QUERY); //--- // long polling con 20 segundos g_tlg_bot_poller.Init(20); g_tlg_bot_poller.AllowedUpdates(); //--- g_bot.Token(InpBotToken); g_bot.ChatId(InpBotChatId); g_bot.SetCommand("start", 0); g_bot.SetCommand("poll", 1); g_bot.SetCommand("reaction", 2); g_bot.SetCommand("foto", 3); g_bot.SetCommand("doc", 4); g_bot.SetCommand("XD", 5); g_bot.SetCommand("All", 6); g_bot.SetCommand("RKeyboard", 7); //--- EventSetMillisecondTimer(1000); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- g_tlg_bot_poller.UnregisterEvent(&g_bot, TSN::TELEGRAMBYLEO_GETUPT_K_MESSAGE); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnTimer(void) { g_tlg_bot_poller.GetUpdates(); } //+------------------------------------------------------------------+ /* #import "string" as string enum ENUM_POSITION_TYPE { POSITION_TYPE_BUY, POSITION_TYPE_SELL }; struct Position { enum ENUM_POSITION_TYPE type; double sl; double tp; double open_price; }; func [inline, notrow] string emoji(const enum ENUM_POSITION_TYPE type) { @static const string: table[2] = { "soriente", "molesto" }; return $table[$type]; } // indicamos que position es una variable que se inyecta en ejecucion #property runtime_var(struct Position: position) void OnPositionOpen() { //--- @const string: emoji = emoji($position.type); @const string: sl = S["SL : " + (B[position.sl != 0.0] ? string.DoubleToString($position.sl) : "")]; //--- @const string: text = U" ## Nueva posicion abierta // Texto de apertura (comentarios se ignoran) {$sl} \"TP\": [$position.tp] \"OpenPrice\": {$position.open_price} ## Summary: Moved pips: {M[$position.tp - $position.sl]} Type: {B[$position.type == POSITION_TYPE_BUY ? \"buy\" : \"sell\"]} - {$emoji} " //--- SendMessage($text) } */ //+------------------------------------------------------------------+