skip to Main Content

I’m trying to send an image buff with cUrl to the telegram API using c++. Just to know I’ m developing on Windows 10.

Here is all I have done.

First I send a photo from my hard drive using curl from terminal using this command:

curl -s -X POST "https://api.telegram.org/bottoken/sendPhoto" -F chat_id=id -F photo="@D:/a.jpg"

On the telegram chat I receive the photo with this command meanwhile on the console in which I did the cUrl request I have a response like this:

{"ok":true,"result":{"message_id":2398,"from":{"id":id,"is_bot":true,"first_name":"botname","username":"stuff"},"chat":{"id":chatid,"first_name":"userdata","username":"userdata","type":"private"},"date":1588929212,"photo":[{"file_id":"reallylongfileid","file_unique_id":"shorterid","file_size":26307,"width":240,"height":320}]}}

If I import this request using the Import tab and selecting raw text in Postman and execute it I have this response:

{
    "ok": false,
    "error_code": 400,
    "description": "Bad Request: wrong HTTP URL specified"
}

If I try to use the postman generated code:

CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
  // I added CURLOPT_VERBOSE 
  curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
  curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
  curl_easy_setopt(curl, CURLOPT_URL, "https://api.telegram.org/bottoken/sendPhoto");
  curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
  curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
  struct curl_slist *headers = NULL;
  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
  curl_mime *mime;
  curl_mimepart *part;
  mime = curl_mime_init(curl);
  part = curl_mime_addpart(mime);
  curl_mime_name(part, "chat_id");
  curl_mime_data(part, "mychatid", CURL_ZERO_TERMINATED);
  part = curl_mime_addpart(mime);
  curl_mime_name(part, "photo");
  curl_mime_data(part, "@D:/a.jpg", CURL_ZERO_TERMINATED);
  curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
  res = curl_easy_perform(curl);
  curl_mime_free(mime);
}
curl_easy_cleanup(curl);

I have this response on the console:

*   Trying 149.154.167.220...
* TCP_NODELAY set
* Connected to api.telegram.org (149.154.167.220) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* SSL certificate problem: self signed certificate in certificate chain
* Closing connection 0

So I added this option to the code I wrote before:

curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);

and the new response is:

*   Trying 149.154.167.220...
* TCP_NODELAY set
* Connected to api.telegram.org (149.154.167.220) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: OU=Domain Control Validated; CN=api.telegram.org
*  start date: Mar 24 13:48:17 2020 GMT
*  expire date: May 23 16:17:38 2022 GMT
*  subjectAltName: host "api.telegram.org" matched cert's "api.telegram.org"
*  issuer: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=http://certs.godaddy.com/repository/; CN=Go Daddy Secure Certificate Authority - G2
*  SSL certificate verify result: self signed certificate in certificate chain (19), continuing anyway.
> POST /botmybottoken/sendPhoto HTTP/1.1
Host: api.telegram.org
Accept: */*
Content-Length: 254
Content-Type: multipart/form-data; boundary=------------------------9b6fc10336ea9470

* We are completely uploaded and fine
* old SSL session ID is stale, removing
< HTTP/1.1 400 Bad Request
< Server: nginx/1.16.1
< Date: Fri, 08 May 2020 09:25:10 GMT
< Content-Type: application/json
< Content-Length: 83
< Connection: keep-alive
< Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
< Access-Control-Allow-Origin: *
< Access-Control-Expose-Headers: Content-Length,Content-Type,Date,Server,Connection
<
{"ok":false,"error_code":400,"description":"Bad Request: wrong HTTP URL specified"}* Connection #0 to host api.telegram.org left intact
* Closing connection 0

If I try to send this image buffer:

    cv::Mat img(260, 301, CV_8UC3, cv::Scalar(0, 0, 0));
    std::vector<uchar> buff;
    std::vector<int> param(2);
    param[0] = cv::IMWRITE_JPEG_QUALITY;
    param[1] = 80;

    cv::imencode(".jpg", img, buff, param);
    std::string strImg((char*)buff.data(), buff.size());

And if I modify the request code only from this:

  curl_mime_data(part, "@D:/a.jpg", CURL_ZERO_TERMINATED);

To this:

  curl_mime_data(part, strImg.data(), strImg.size());

I have this response in the console:

*   Trying 149.154.167.220...
* TCP_NODELAY set
* Connected to api.telegram.org (149.154.167.220) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: OU=Domain Control Validated; CN=api.telegram.org
*  start date: Mar 24 13:48:17 2020 GMT
*  expire date: May 23 16:17:38 2022 GMT
*  subjectAltName: host "api.telegram.org" matched cert's "api.telegram.org"
*  issuer: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=http://certs.godaddy.com/repository/; CN=Go Daddy Secure Certificate Authority - G2
*  SSL certificate verify result: self signed certificate in certificate chain (19), continuing anyway.
> POST /botmybottoken/sendPhoto HTTP/1.1
Host: api.telegram.org
Accept: */*
Content-Length: 2164
Content-Type: multipart/form-data; boundary=------------------------f5bde0e2e0ef8114
Expect: 100-continue

* old SSL session ID is stale, removing
< HTTP/1.1 100 Continue
* We are completely uploaded and fine
< HTTP/1.1 400 Bad Request
< Server: nginx/1.16.1
< Date: Fri, 08 May 2020 09:30:34 GMT
< Content-Type: application/json
< Content-Length: 128
< Connection: keep-alive
< Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
< Access-Control-Allow-Origin: *
< Access-Control-Expose-Headers: Content-Length,Content-Type,Date,Server,Connection
<
{"ok":false,"error_code":400,"description":"Bad Request: wrong remote file identifier specified: Wrong character in the string"}* Connection #0 to host api.telegram.org left intact
* Closing connection 0

I don’t want to use any c++ telegram bot library because I have just to send a Message or a photo.
I’ m able to send a message with cUrl code.
With photos, I have some problems.
Because I have to do this two simple actions I prefer to use only cUrl and nothing else.
I need help cause I’m not understanding what’s wrong.
I know I write a lot but I wish this could help you to understand everything better and faster.

Thank you!

2

Answers


  1. int sendTelegramPhoto(string chat_id, string path_to_photo, string caption = NULL){
        CURL *curl;
        CURLcode response;
        curl_global_init(CURL_GLOBAL_ALL);
        curl = curl_easy_init();
        if (curl)
        {
            curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
            curl_easy_setopt(curl, CURLOPT_POST, 1);
            curl_easy_setopt(curl, CURLOPT_URL,     "https://api.telegram.org/bottoken/sendPhoto");
            curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
            struct curl_slist *headers = NULL;
            curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
            curl_slist_append(headers, "Content-Type: multipart/form-data");
            curl_slist_append(headers, "charset=utf-8");
            curl_mime *mime;
            curl_mimepart *part;
            mime = curl_mime_init(curl);
            part = curl_mime_addpart(mime);
            curl_mime_name(part, "chat_id");
            curl_mime_data(part, chat_id.c_str(), CURL_ZERO_TERMINATED);
            part = curl_mime_addpart(mime);
            curl_mime_name(part, "photo");
            curl_mime_filedata(part, path_to_photo.c_str());
            curl_mime_type(part, "image/jpeg");
            part = curl_mime_addpart(mime);
            curl_mime_name(part, "caption");
            curl_mime_data(part, caption.c_str().c_str(), CURL_ZERO_TERMINATED);
            curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
            response = curl_easy_perform(curl);
            curl_mime_free(mime);
            curl_slist_free_all(headers);
        }
        curl_easy_cleanup(curl);
        return 0;
    }
    
    Login or Signup to reply.
  2. cv::Mat img(260, 301, CV_8UC3, cv::Scalar(0, 0, 0));
    std::vector<uchar> buff;
    std::vector<int> param(2);
    param[0] = cv::IMWRITE_JPEG_QUALITY;
    param[1] = 80;
    
    cv::imencode(".jpg", img, buff, param);
    std::string strImg((char*)buff.data(), buff.size());
    
    CURLcode ret;
    CURL* hnd;
    curl_mime* mime1;
    curl_mimepart* part1;
    
    mime1 = NULL;
    
    hnd = curl_easy_init();
    curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
    curl_easy_setopt(hnd, CURLOPT_URL, "https://api.telegram.org/bottoken/sendPhoto");
    curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L);
    mime1 = curl_mime_init(hnd);
    part1 = curl_mime_addpart(mime1);
    curl_mime_data(part1, "mychatid", CURL_ZERO_TERMINATED);
    curl_mime_name(part1, "chat_id");
    part1 = curl_mime_addpart(mime1);
    curl_mime_data(part1, strImg.data(), strImg.size());
    
    curl_mime_filename(part1, "myimage.jpg");
    
    curl_mime_name(part1, "photo");
    curl_easy_setopt(hnd, CURLOPT_MIMEPOST, mime1);
    curl_easy_setopt(hnd, CURLOPT_USERAGENT, "curl/7.87.0-DEV");
    curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
    curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
    curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
    curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
    
    ret = curl_easy_perform(hnd);
    
    ...
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search