skip to Main Content

I’m writing a Telegram bot in Julia and I can’t figure out how to send files correctly.

I’ve seen similar questions for other languages but it wasn’t helpful.

Currently, I have such function:

function sendDoc(chat, fileName::String)
    file = open(fileName)
    url = string(base_url, "sendDocument")
    mp = HTTP.Multipart(basename(fileName), file)
    query = Dict("chat_id" => chat)
    HTTP.post(url; query=query, files=Dict("document" => mp))

    close(file)
end

I try it on a simple test.txt file with the content abc so the size of a file or it’s name can’t be a reason for any errors.

What I get from it (and also in case if I use file instead of mp) is an HTTP 400 error (I removed some parts for privacy purposes):

ERROR: LoadError: HTTP.ExceptionRequest.StatusError(400, "POST", "/bot/sendDocument?chat_id=", HTTP.Messages.Response(v"1.1.0", 400, Pair{SubString{String},SubString{String}}["Server" => "nginx/1.16.1", "Date" => "Thu, 12 Mar 2020 GMT", "Content-Type" => "application/json", "Content-Length" => "94", "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"], UInt8[0x7b, 0x22, 0x6f, 0x6b, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73  …  0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x7d], HTTP.Messages.Request("POST", "/bot/sendDocument?chat_id=", v"1.1.0", Pair{SubString{String},SubString{String}}["Host" => "api.telegram.org", "User-Agent" => "HTTP.jl/1.3.1", "Content-Length" => "0"], UInt8[], HTTP.Messages.Response(#= circular reference @-2 =#), 1, nothing)))

I also tried putting mp or file in body instead of files but then I get the following:

┌ Info: Error in @async writebody task. Server likely closed the connection unexpectedly. Only an issue if unable to read the response and this error gets re-thrown. 
│   exception =
│    MethodError: no method matching write(::HTTP.Streams.Stream{HTTP.Messages.Response,HTTP.ConnectionPool.Transaction{MbedTLS.SSLContext}}, ::Pair{String,IOStream})
│    Closest candidates are:
│      write(::IO, ::Any) at io.jl:582
│      write(::IO, ::Any, ::Any...) at io.jl:584
│      write(::IO, ::Complex) at complex.jl:217

Including the file in query is also something I could try but then it would be in the URL and I’d be very limited in file size.

The 400 error looks the same as if it would be missing a field, so I assume that Telegram can’t see the Dict("document" => mp), but at the same time error includes UInt8[0x7b, … 0x7d] which looks like the contents of the file. How do I make it right?

3

Answers


  1. Chosen as BEST ANSWER

    Turns out, it's not HTTP.Multipart that I needed, it's HTTP.Form.

    The following function works:

    function sendDoc(chat, fileName::String)
        url = string(base_url, "sendDocument")
        file = open(fileName)
        query = Dict("chat_id" => chat)
        HTTP.post(url, query=query; body=HTTP.Form(Dict("document" => file)))
    
        close(file)
    end
    

  2. Let’s say you have a photo in your directory "Foto.jpg". To send a photo, you would need this:

    fileName = "Foto.jpg"
    url_photo = string("https://api.telegram.org/bot",bot_token,"/sendPhoto")
    file = open(fileName)
    query = Dict("chat_id" => bot_manu)
    HTTP.post(url_photo, query=query; body=HTTP.Form(Dict("photo" => file)))
    close(file)
    

    Where ‘bot_manu’ should be your chat id, ‘bot_token’ is the bot id token. Hope this helps for those who wanted to send a photo. To get ‘bot_manu’ and ‘bot_token’ I used BotFather.

    Login or Signup to reply.
  3. If you want to, you may use Telegram.jl package, which in particular includes support for document and images sending.

    You can do it like this

    using Telegram, Telegram.API
    tg = TelegramClient(bot_token; chat_id = chat)
    
    open("picture.png", "r") do io
      sendPhoto(photo = io)
    end
    

    Here bot_token and chat are bot token and chat id.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search