2026-09-23 15:26:06 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| CommandsApi.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_COMMANDSAPI_MQH
|
| | | #define TELEGRAMBYLEO_SRC_COMMANDSAPI_MQH
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | #include "Events.mqh"
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-09-24 08:24:12 -05:00 | | | namespace TSN
|
| | | {
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-09-25 09:59:13 -05:00 | | | class CTelegramCommandBot : public CTelegramBot
|
2026-09-23 15:26:06 -05:00 | | | {
|
2026-09-24 08:24:12 -05:00 | | | protected:
|
| | | CHashMapFast(ulong, int) m_commands;
|
| | | // por ahora si quizas luego lista de priridad con un sorted list
|
| | |
|
| | | //---
|
| | | bool ResolveCommand(const uchar& in[], int i, int len);
|
2026-09-25 09:59:13 -05:00 | | | bool IsMyUsername(const uchar& in[], int i, int e);
|
2026-09-23 15:26:06 -05:00 | | |
|
| | | //--- Cada comando
|
| | | virtual void OnCommand(int command_idx, long chat_id, CJsonNode& json) {}
|
| | |
|
| | | public:
|
| | | CTelegramCommandBot(void) {}
|
| | | ~CTelegramCommandBot(void) {}
|
| | |
|
| | | //---
|
2026-09-24 08:24:12 -05:00 | | | void SetCommand(const string& command, int idx);
|
| | | bool RemoveCommand(const string& command);
|
2026-09-23 15:26:06 -05:00 | | |
|
2026-09-24 08:24:12 -05:00 | | | //---
|
| | | void OnMessage(CJsonNode& node) override final;
|
2026-09-23 15:26:06 -05:00 | | | };
|
2026-09-24 08:24:12 -05:00 | | |
|
2026-09-25 09:59:13 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | bool CTelegramCommandBot::IsMyUsername(const uchar& in[], int i, int e)
|
| | | {
|
| | | //---
|
| | | // 1. e apnta a la posicion "end + 1"
|
| | |
|
| | | //---
|
| | | const int my_len = StringLen(m_me.username); // len del user name que tenemos
|
| | | const int l = (e - i); // len de lo que encontramos
|
| | | if(l != my_len) // no es igual...
|
| | | return false;
|
| | |
|
| | | //---
|
| | | for(int x = 0; x < l; x++)
|
| | | if(in[i++] != m_me.username[x])
|
| | | return false;
|
| | |
|
| | | //---
|
| | | return true;
|
| | | }
|
| | |
|
2026-09-24 08:24:12 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | bool CTelegramCommandBot::ResolveCommand(const uchar &in[], int i, int len)
|
| | | {
|
2026-09-24 12:18:36 -05:00 | | | // len = min
|
2026-09-24 08:24:12 -05:00 | | | len += i;
|
2026-09-24 12:18:36 -05:00 | | | i++; // salta \
|
2026-09-24 08:24:12 -05:00 | | |
|
| | | //---
|
| | | // 1. una sola pasada para veriicar y hash (no dos)
|
| | | ulong h = FNV_OFFSET_BASIS;
|
2026-09-24 12:18:36 -05:00 | | | uchar c = in[i];
|
2026-09-24 08:24:12 -05:00 | | | while(true)
|
| | | {
|
2026-09-24 12:18:36 -05:00 | | | if(c == ' ' || c == '@')
|
2026-09-24 08:24:12 -05:00 | | | break;
|
| | |
|
| | | //--
|
| | | h ^= c;
|
| | | h *= FNV_PRIME;
|
| | |
|
| | | //--
|
| | | if(++i >= len)
|
| | | break;
|
2026-09-24 12:18:36 -05:00 | | |
|
| | | //---
|
| | | c = in[i];
|
| | | }
|
| | |
|
| | | //---
|
| | | if(i < len && c == '@')
|
| | | {
|
| | | //---
|
| | | i++; // salta '@'
|
| | | int bot_start = i;
|
| | | while(i < len && in[i] != ' ')
|
| | | i++;
|
| | |
|
| | | //---
|
| | | if(!IsMyUsername(in, bot_start, i))
|
| | | return false;
|
2026-09-24 08:24:12 -05:00 | | | }
|
| | |
|
| | | //---
|
| | | // vol en vez de int (ternario menos par ael TryGet==true? 1 : value)
|
| | | return m_commands.ContainsKey(h);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | void CTelegramCommandBot::SetCommand(const string &command, int idx)
|
| | | {
|
| | | //--- hash
|
| | | ulong h = FNV_OFFSET_BASIS;
|
| | | const int len = StringLen(command);
|
| | | FNV1a_64_AsM_Str(command, len, h, FNV_PRIME)
|
| | |
|
| | | //---
|
| | | if(m_commands.ReserveSlot(h)) // no existe
|
| | | {
|
| | | const uint p = m_commands.m_last_pos_tbl;
|
| | | m_commands.m_table[p].key = h;
|
| | | m_commands.m_table[p].value = idx;
|
| | | }
|
| | | else
|
| | | {
|
| | | // Ya existe... modificamos el valor
|
| | | m_commands.m_table[m_commands.m_last_pos_tbl].value = idx;
|
| | | }
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | bool CTelegramCommandBot::RemoveCommand(const string &command)
|
| | | {
|
| | | //--- hash
|
| | | ulong h = FNV_OFFSET_BASIS;
|
| | | const int len = StringLen(command);
|
| | | FNV1a_64_AsM_Str(command, len, h, FNV_PRIME)
|
| | |
|
| | | //---
|
| | | return m_commands.Remove(h);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | void CTelegramCommandBot::OnMessage(CJsonNode &node)
|
| | | {
|
| | | //---
|
| | | CJsonNode text = node["text"];
|
| | | const int start = text.StrStart();
|
| | | const int len = text.StrLenRaw();
|
| | | if(!text.IsValid() || len < 1 || text.m_ctx.m_raw[start] != '/')
|
| | | return;
|
| | |
|
| | | //---
|
| | | //parseamos el texto inplace (sobre buffer ucahr) sin copia y conusltmaos el indice del grupo (commmando) via hashmap
|
2026-09-24 12:18:36 -05:00 | | | if(!ResolveCommand(text.m_ctx.m_raw, start, len))
|
2026-09-24 08:24:12 -05:00 | | | {
|
| | | return;
|
| | | }
|
| | |
|
| | | //---
|
| | | const uint p = m_commands.m_last_pos_tbl;
|
| | | OnCommand(m_commands.m_table[p].value, node["chat"]["id"].ToInt(0), node);
|
2026-09-23 15:26:06 -05:00 | | | }
|
2026-09-24 08:24:12 -05:00 | | | }
|
2026-09-23 15:26:06 -05:00 | | | //+------------------------------------------------------------------+
|
| | | #endif // TELEGRAMBYLEO_SRC_COMMANDSAPI_MQH
|