Обсуждение статьи "Создание бота для Telegram на языке MQL5" - страница 4

 
Rashid Umarov:
Андрей, нужно заменить приложенные коды в статье? Прошу писать в таких случаях модераторам , чтобы они это сделали, хорошо?
Да, Рашид, необходимо обновить архив с кодами. Я первым делом написал об этом модератору пару дней назад.
 
Andrey Voytenko:
Да, Рашид, необходимо обновить архив с кодами. Я первым делом написал об этом модератору пару дней назад.
Архив к статье обновлен. Извиняюсь за задержку.
 

Доброго времени суток Andrey Voytenko! Благодарность за статью, только вот не получается принять и вывести в Алерт сообщение из телеграма следующим образом (каждый раз возвращает пустой алерт,то есть сам факт нового сообщения детектиться, но возвращает пустую переменную):

 

   void ProcessMessages(void)
     {
      for(int i=0; i<m_chats.Total(); i++)
        {
         CCustomChat *chat=m_chats.GetNodeAtIndex(i);
         //--- if the message is not processed
         if(!chat.m_new_one.done)
           {
           chat.m_new_one.done=true;
            string text=chat.m_new_one.message_text;
Alert(text);
            //--- start
            if(text=="/start")
               SendMessage(chat.m_id,"Hello, world! I am bot. \xF680");

            //--- help
            if(text=="/help")
               SendMessage(chat.m_id,"My commands list: \n/start-start chatting with me \n/help-get help");
           }
        }
     }


 

 
Добрый день.

Попробовал сделать под себя бот, чтобы при появлении сделки отправлял скрин в телеграмм.

Отправляется через раз почему то, не могли бы вы посмотреть в чем проблема ?

правил только этот файл, который во вложении.
Файлы:
 

Роман, если вам бот нужен только для отправки скриншотов, то можно сделать так:

1. Узнайте у бота @MyTelegramID_bot‌ номер вашего чата.

2. Напишите простого бота который будет проверять наличие новых позиций и отправлять картинки в чат с указанным ID. Пример такой:

#include <Telegram.mqh>
//+------------------------------------------------------------------+
//|   Input parameters                                               |
//+------------------------------------------------------------------+
input ENUM_LANGUAGES    InpLanguage=LANGUAGE_EN;//Language
input string            InpToken="";//Token
input long              ChatId=0;   //Chat ID
//---
CCustomBot bot;
int pos_count;
//+------------------------------------------------------------------+
int OnInit()
  {
   bot.Token(InpToken);
   int res=bot.GetMe();
   if(res!=0)
     {
      Print(GetErrorDescription(res));
     }
   pos_count=PositionCount(_Symbol);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
void OnTick()
  {
   int pos_count_new=PositionCount(_Symbol);
   if(pos_count_new>pos_count)
     {
      pos_count=pos_count_new;
      int result=SendScreenShot(ChatId,_Symbol,0,NULL);
      if(result!=0)
         Print(GetErrorDescription(result,InpLanguage));
     }
  }
//+------------------------------------------------------------------+
int PositionCount(const string _symbol)
  {
   int count=0;
   int orders_total=OrdersTotal();
   for(int i=0; i<orders_total; i++)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         PrintError(ERR_ORDER_SELECT);
         return(-1);
        }
      //---
      if(_symbol==NULL || OrderSymbol()==_symbol)
         count++;
     }
//---  
   return(count);
  }
//+------------------------------------------------------------------+
int SendScreenShot(const long _chat_id,
                   const string _symbol,
                   const ENUM_TIMEFRAMES _period,
                   const string _template=NULL)
  {
   int result=0;

   long chart_id=ChartOpen(_symbol,_period);
   if(chart_id==0)
      return(ERR_CHART_NOT_FOUND);

   ChartSetInteger(ChartID(),CHART_BRING_TO_TOP,true);

//--- updates chart
   int wait=60;
   while(--wait>0)
     {
      if(SeriesInfoInteger(_symbol,_period,SERIES_SYNCHRONIZED))
         break;
      Sleep(500);
     }

   if(_template!=NULL)
      if(!ChartApplyTemplate(chart_id,_template))
         PrintError(_LastError,InpLanguage);

   ChartRedraw(chart_id);
   Sleep(500);

   ChartSetInteger(chart_id,CHART_SHOW_GRID,false);

   ChartSetInteger(chart_id,CHART_SHOW_PERIOD_SEP,false);

   string filename=StringFormat("%s%d.gif",_symbol,_period);

   if(FileIsExist(filename))
      FileDelete(filename);
   ChartRedraw(chart_id);

   Sleep(100);

//      if(ChartScreenShot(chart_id,filename,800,600,ALIGN_RIGHT))
   if(ChartScreenShot(chart_id,filename,1024,768,ALIGN_RIGHT))
     {
      Sleep(100);

      bot.SendChatAction(_chat_id,ACTION_UPLOAD_PHOTO);

      //--- waitng 30 sec for save screenshot
      wait=60;
      while(!FileIsExist(filename) && --wait>0)
         Sleep(500);

      //---
      string screen_id;
      result=bot.SendPhoto(_chat_id,filename,screen_id,_symbol+"_"+StringSubstr(EnumToString(_period),7));
     }

   ChartClose(chart_id);
   return(result);
  }

//+------------------------------------------------------------------+
 

Спасибо за интересную статью. Есть ошибка в коде (на скриншоте видно):

Ошибка при отправке фото, заголовок

Требуются исправления в методе SendPhoto класса CCustomBot. Предлагаю такой вариант:

   int SendPhoto(const string _channel_name,
                 const string _local_path,
                 string &_photo_id,
                 const string _caption=NULL,
                 const bool _common_flag=false,
                 const int _timeout=10000)
     {
      //---
      // const long _chat_id
      //---
      
      if(m_token==NULL)
         return(ERR_TOKEN_ISEMPTY);

      string name=StringTrim(_channel_name);
      if(StringGetCharacter(name,0)!='@')
         name="@"+name;
      
      
      ResetLastError();
      //--- copy file to memory buffer
      if(!FileIsExist(_local_path,_common_flag))
         return(ERR_FILE_NOT_EXIST);

      //---
      int flags=FILE_READ|FILE_BIN|FILE_SHARE_WRITE|FILE_SHARE_READ;
      if(_common_flag)
         flags|=FILE_COMMON;

      //---
      int file=FileOpen(_local_path,flags);
      if(file<0)
         return(_LastError);

      //---
      int file_size=(int)FileSize(file);
      uchar photo[];
      ArrayResize(photo,file_size);
      FileReadArray(file,photo,0,file_size);
      FileClose(file);

      //--- create boundary: (data -> base64 -> 1024 bytes -> md5)
      uchar base64[];
      uchar key[];
      CryptEncode(CRYPT_BASE64,photo,key,base64);
      //---
      uchar temp[1024]={0};
      ArrayCopy(temp,base64,0,0,1024);
      //---
      uchar md5[];
      CryptEncode(CRYPT_HASH_MD5,temp,key,md5);
      //---
      string hash=NULL;
      int total=ArraySize(md5);
      for(int i=0;i<total;i++)
         hash+=StringFormat("%02X",md5[i]);
      hash=StringSubstr(hash,0,16);
      //---

      //--- WebRequest
      uchar result[];
      string result_headers;

      string url=StringFormat("%s/bot%s/sendPhoto",TELEGRAM_BASE_URL,m_token);

      string part1="Content-Type: multipart/form-data; boundary="+hash+"\r\n";
      part1+="\r\n";

      //--- add chart_id
      part1+="--"+hash+"\r\n";
      part1+="Content-Disposition: form-data; name=\"chat_id\"\r\n";
      part1+="\r\n";
      part1+=name; //IntegerToString(_chat_id);
      part1+="\r\n";

      //--- add caption
      if(_caption!=NULL)
        {
         part1+="--"+hash+"\r\n";
         part1+="Content-Disposition: form-data; name=\"caption\"\r\n";
         //part1+="Content-Type: text/plain\r\n";
         //part1+="Content-Transfer-Encoding: quoted-printable\r\n";
         part1+="\r\n";
         //part1+=UrlEncode(_caption);
         part1+=_caption;
         part1+="\r\n";
        }

      //--- add image
      part1+="--"+hash+"\r\n";
      part1+="Content-Disposition: form-data; name=\"photo\"; filename=\"lampash.gif\"\r\n";
      part1+="\r\n";

      //--- 1
      uchar array1[];
      int size1=StringLen(part1);
      StringToCharArray(part1,array1,0,size1);

      //--- 2
      //photo
      int size2=ArraySize(photo);

      //---
      string part3="\r\n--"+hash+"--\r\n";
      int size3=StringLen(part3);
      uchar array3[];
      StringToCharArray(part3,array3,0,size3);

      //---
      uchar data[];
      ArrayResize(data,size1+size2+size3);
      ArrayCopy(data,array1,0);
      ArrayCopy(data,photo,size1);
      ArrayCopy(data,array3,size1+size2);

      //---
      string headers="Content-Type: multipart/form-data; boundary="+hash+"\r\n";
      int res=WebRequest("POST",url,headers,_timeout,data,result,result_headers);
      if(res==200)//OK
        {
         //--- delete BOM
         int start_index=0;
         int size=ArraySize(result);
         for(int i=0; i<fmin(size,8); i++)
           {
            if(result[i]==0xef || result[i]==0xbb || result[i]==0xbf)
               start_index=i+1;
            else
               break;
           }

         //---
         string out=CharArrayToString(result,start_index,WHOLE_ARRAY,CP_UTF8);

         //--- parse result
         CJAVal js(NULL,jtUNDEF);
         bool done=js.Deserialize(out);
         if(!done)
            return(ERR_JSON_PARSING);

         //--- get error description
         bool ok=js["ok"].ToBool();
         if(!ok)
            return(ERR_JSON_NOT_OK);

         total=ArraySize(js["result"]["photo"].m_e);
         for(int i=0; i<total; i++)
           {
            CJAVal image=js["result"]["photo"].m_e[i];

            long image_size=image["file_size"].ToInt();
            if(image_size<=file_size)
               _photo_id=image["file_id"].ToStr();
           }

         return(0);
        }
      else
        {
         if(res==-1)
           {
            string out=CharArrayToString(result,0,WHOLE_ARRAY,CP_UTF8);
            //Print(out);
            return(_LastError);
           }
         else
           {
            if(res>=100 && res<=511)
              {
               string out=CharArrayToString(result,0,WHOLE_ARRAY,CP_UTF8);
               //Print(out);
               return(ERR_HTTP_ERROR_FIRST+res);
              }
            return(res);
           }
        }
      //---        
      return(0);
     }
 
Andrey Emelyanov:

Спасибо за интересную статью. Есть ошибка в коде (на скриншоте видно):

Требуются исправления в методе SendPhoto класса CCustomBot. Предлагаю такой вариант:

Благодарю за сообщение. Однако, ваш исправленный вариант работает только с латиницей.

По логике, нужно преобразовать строку в массив с кодировкой UTF-8 и подставить в качестве caption в тело запроса.

Мой вариант в приложении.

Файлы:
Telegram.mqh  64 kb
 
               if(index==-1)
                 {
                  m_chats.Add(new CCustomChat);
                  CCustomChat *chat=m_chats.GetLastNode();
                  chat.m_id=msg.chat_id;
                  chat.m_time=TimeLocal();
                  chat.m_state=0;
                  chat.m_new_one.message_text=msg.message_text;
                  chat.m_new_one.done=false;
                 }
               //--- update chat message
               else
                 {
                  CCustomChat *chat=m_chats.GetNodeAtIndex(index);
                  chat.m_time=TimeLocal();
                  chat.m_new_one.message_text=msg.message_text;
                  chat.m_new_one.done=false;
                 }

это код из процедуры    int   GetUpdates()

да структура msg заполняется отлично но в указатель на чат из нее копирутеся только

                  chat.m_time=TimeLocal();
                  chat.m_new_one.message_text=msg.message_text;
                  chat.m_new_one.done=false;
 

Если не хватает информации, можно добавить её так:

chat.m_new_one=msg;
 
Andrey Voytenko:

Если не хватает информации, можно добавить её так:

Ошибка выскакивает в CCustomMessage msg = {0}; и при отправке сообщения в канал, Error: HTTP request failed. В чем может быть проблема?

Причина обращения: