0

Here is the situation.

I have an Android app, which can send voice file with HTTP POST anywhere I specify. Also I would like to download these voice files to Telegram bot automatically. I wrote a PHP bot and I can accept and translate to Telegram any fields that come in said POST. One thing I miss is the file itself.

I don't know how to "say" to telegram API I download a file.

So what do I have: present file in $_FILE stream (I can read the name of it), I throw it in sendVoice function as $voice, also I do know I have to use simple multipart/form-data POST method to send file.

My question is: is it possible to use something but CURL to POST right from PHP? If not, what am I missing then? Other methods I use are messages and photo sending via file_get_contents(), I wonder if it's still suitable for voice file?

Here is the code I have now, which I found somewhere (I have 0 cURL knowledge):

function sendVoice($chat_id, $voice, $caption) {
    $boundary = uniqid();
    $delimiter = '-------------' . $boundary;
    $fields = array(
        "chat_id" => $chat_id,
        "caption" => $caption
    );

    $post_data = build_data_files($boundary, $fields, $voice);

    $ch = curl_init($GLOBALS['api'].'/sendVoice');
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        //"Authorization: Bearer $TOKEN",
        "Content-Type: multipart/form-data; boundary=" . $delimiter,
        "Content-Length: " . strlen($post_data))
        );
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
    curl_exec($ch);
    curl_close($ch);
}


function build_data_files($boundary, $fields, $files){
    $data = '';
    $eol = "\r\n";
    $delimiter = '-------------' . $boundary;
    foreach ($fields as $name => $content) {
        $data .= "--" . $delimiter . $eol
            . 'Content-Disposition: form-data; name="' . $name . "\"".$eol.$eol
            . $content . $eol;
    }
    foreach ($files as $name => $content) {
        $data .= "--" . $delimiter . $eol
            . 'Content-Disposition: form-data; name="' . $name . '"; filename="' . $name . '"' . $eol
            //. 'Content-Type: image/png'.$eol
            . 'Content-Transfer-Encoding: binary'.$eol
            ;
        $data .= $eol;
        $data .= $content . $eol;
    }
    $data .= "--" . $delimiter . "--".$eol;
    return $data;
}

1 Answers1

0

This was actally much easier. Since we have file present in $_FILES, we can do all of the cURL in just sendVoice() function without any hassle of rebinding boundaries or specifying content types.

Here is the final code which worked for me:

function sendVoice($chat_id, $voice, $caption) {
    $filepath = realpath($_FILES['file']['tmp_name']);
    $post_data = array(
        'chat_id' => $chat_id,
        'voice' => new CURLFile($filepath),
        'caption' => $caption
    );
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $GLOBALS['api'].'/sendVoice');
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    curl_exec($ch);
    curl_close($ch); 
}

That will download an .OGG file as voice message (because I do not want any files to appear in my music player). Later it is possible to just add more fields such as duration in $post_data array and Telegram would eat them accordingly.