Skip to content
Advertisement

Discord webhook returnes error when called from Forge mod

What I want is to send a file over a discord webhook using java code.

I created a perfectly working code using the knowledge I gained from this stackoverflow post about curl requests in java and this Discord webhooks guide about sending attachments.

The problem is, if I call the exact same code, that works perfectly from a standard java programm, from a forge 1.8.9 mod instead, it results in the following error:

403: Forbidden
error code: 1010

Does anyone know how to solve this? And how can Discord even distinguish between the two?


The following is code contains the central method. LINE_FEED, addFormField and addFilePart are directly from the mentioned stackoverflow post and CHARSET = "UTF-8". channel_id and token are the custom values from the Discord webhook.

public boolean sendFile(String username, String message, File file) {
    // mostly from https://stackoverflow.com/a/34409142/6307611
    try {
        boundary = "===" + System.currentTimeMillis() + "===";
        URL url = new URL("https://discord.com/api/webhooks/" + channel_id + "/" + token);
        HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
        urlConnection.setConnectTimeout(5000);
        urlConnection.setUseCaches(false);
        urlConnection.setDoOutput(true);
        urlConnection.setDoInput(true);
        urlConnection.setRequestProperty("content-type", "multipart/form-data; boundary=" + boundary);

        OutputStream os = urlConnection.getOutputStream();
        PrintWriter w = new PrintWriter(new OutputStreamWriter(os, CHARSET), true);
        if (message != null)
            addFormField(w, "payload_json",
                    "{"username": "" + username + "", "content": "" + message + ""}");
        else
            addFormField(w, "payload_json", "{"username": "" + username + ""}");
        addFilePart(os, w, "file", file);
        w.append(LINE_FEED).flush();
        w.append("--" + boundary + "--").append(LINE_FEED);
        w.close();
        os.close();
        int code = urlConnection.getResponseCode();

        // error handling
        System.out.println(code + ": " + urlConnection.getResponseMessage());
        BufferedReader br = new BufferedReader(new InputStreamReader(
                (code >= 100 && code < 400) ? urlConnection.getInputStream() : urlConnection.getErrorStream()));
        StringBuilder sb = new StringBuilder();
        String buffer;
        while ((buffer = br.readLine()) != null)
            sb.append(buffer);
        System.out.println(sb.toString());

        urlConnection.disconnect();
        return code >= 200 && code < 300;
    } catch (MalformedURLException ignored) {
        return false;
    } catch (IOException ignored) {
        return false;
    }
}

Advertisement

Answer

Got it! The question “how can Discord even distinguish between the two” gave me the idea to set the user-agent to a fixed value – and solved the problem.

//[...]
urlConnection.setDoInput(true);
        
// this line solved the problem
urlConnection.setRequestProperty("user-agent", "Mozilla/5.0 ");

urlConnection.setRequestProperty("content-type", "multipart/form-data; boundary=" + boundary);
//[...]
Advertisement