2

I want to send discord.png to a text channel using Python and the Discord API, but I keep getting an error:

{"message": "Cannot send an empty message", "code": 50006"}

I think I've done everything as the Documentation said, and I don't know what's the problem. I know, I could just use an already existing python library for this (like discord.py) but I'm only playing with the API, and I cant't figure out what is the issue here.

headers = {"Authorization": f"Bot {TOKEN}", "Content-Type": "multipart/form-data"}

f = open("discord.png", "rb")
file_data = f.read()
f.close()

file_data = base64.b64encode(file_data).decode()

payload_json = '{"content": "Discord", "tts": False}'
data = {
    "content": "Discord",
    "tts": False,
    "file": file_data
}

headers["User-Agent"] = "DiscordBot"
#headers["Content-Type"] = "multipart/form-data" #edited but then realised i already set the content-type
headers["Content-Disposition"] = 'form-data; name="file" filename="discord.png"'

r = requests.post(f"{http_api}/channels/{CHANNEL_ID}/messages", data, headers=headers)
print(r.content)

1 Answers1

1

There are a couple tiny mistakes in your code, but the main issue here is actually that the Discord documentation is very misleading.

When sending a file (or multiple files) this is not done by sending the contents in the file field of the request as the documentation indicates. Rather, the file(s) should be in the body of the request, as in the second example here:

POST /test.html HTTP/1.1
Host: example.org
Content-Type: multipart/form-data;boundary="boundary"

--boundary
Content-Disposition: form-data; name="field1"

value1
--boundary
Content-Disposition: form-data; name="field2"; filename="example.txt"

value2
--boundary--

The requests module allows us to do this very conveniently with the files parameter:

data = {"payload_json": payload_json}
headers = {"Authorization": f"Bot {TOKEN}", "User-Agent": "DiscordBot"}
r = requests.post(f"{http_api}/channels/{CHANNEL_ID}/messages", data,
                  files={"discord.png": file_data}, headers=headers)

And note there is no need to set the Content-Type or Content-Disposition headers – requests will take care of that for you.

For more examples/explanation of making requests with the files parameter, see this question.

Will
  • 451
  • 6
  • 17