Skip to content

Support editing attachments in API v10 #83

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ plugins {
}

val major = "0"
val minor = "8"
val patch = "2"
val minor = "9"
val patch = "0"

group = "club.minnced"
version = "$major.$minor.$patch"
Expand Down Expand Up @@ -46,7 +46,7 @@ repositories {
val versions = mapOf(
"slf4j" to "1.7.32",
"okhttp" to "4.10.0",
"json" to "20210307",
"json" to "20220320",
"jda" to "5.0.0-alpha.13",
"discord4j" to "3.2.2",
"javacord" to "3.4.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package club.minnced.discord.webhook;

public class LibraryInfo {
public static final int DISCORD_API_VERSION = 9;
public static final int DISCORD_API_VERSION = 10;
public static final String VERSION_MAJOR = "@MAJOR@";
public static final String VERSION_MINOR = "@MINOR@";
public static final String VERSION_PATCH = "@PATCH@";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package club.minnced.discord.webhook.receive;

import club.minnced.discord.webhook.send.MessageAttachment;
import org.jetbrains.annotations.NotNull;
import org.json.JSONObject;
import org.json.JSONPropertyName;
Expand All @@ -26,7 +27,7 @@
* <br>This does not actually contain the file but only meta-data
* useful to retrieve the actual attachment.
*/
public class ReadonlyAttachment implements JSONString {
public class ReadonlyAttachment extends MessageAttachment implements JSONString {
private final String url;
private final String proxyUrl;
private final String fileName;
Expand All @@ -37,6 +38,7 @@ public class ReadonlyAttachment implements JSONString {
public ReadonlyAttachment(
@NotNull String url, @NotNull String proxyUrl, @NotNull String fileName,
int width, int height, int size, long id) {
super(id, fileName);
this.url = url;
this.proxyUrl = proxyUrl;
this.fileName = fileName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import club.minnced.discord.webhook.IOUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.json.JSONObject;

import java.io.File;
import java.io.FileInputStream;
Expand All @@ -28,15 +30,25 @@
* Internal representation of attachments for outgoing messages
*/
public class MessageAttachment {
private static final byte[] empty = new byte[0];
private final long id;
private final String name;
private final byte[] data;

protected MessageAttachment(long id, @NotNull String name) {
this.id = id;
this.name = name;
this.data = empty;
}

MessageAttachment(@NotNull String name, @NotNull byte[] data) {
this.id = 0;
this.name = name;
this.data = data;
}

MessageAttachment(@NotNull String name, @NotNull InputStream stream) throws IOException {
this.id = 0;
this.name = name;
try (InputStream data = stream) {
this.data = IOUtil.readAllBytes(data);
Expand All @@ -47,6 +59,50 @@ public class MessageAttachment {
this(name, new FileInputStream(file));
}

/**
* Create an instance of this class with the provided ID and name.
*
* <p>This can be used in {@link club.minnced.discord.webhook.send.WebhookMessageBuilder#addFile(MessageAttachment)}
* to retain existing attachments on a message for an edit request.
* The name parameter can also be used to rename the attachment.
*
* @param id
* The snowflake ID for this attachment (must exist on the message you edit9
* @param name
* The new name for the attachment, or null to keep existing name
*
* @throws java.lang.IllegalArgumentException
* If the provided ID is not a valid snowflake
*
* @return The attachment instance
*/
@NotNull
public static MessageAttachment fromId(long id, @Nullable String name) {
if (id > WebhookMessage.MAX_FILES)
throw new IllegalArgumentException("MessageAttachment ID must be higher than " + WebhookMessage.MAX_FILES + ".");
return new MessageAttachment(id, name == null ? "" : name);
}


/**
* Create an instance of this class with the provided ID and name.
*
* <p>This can be used in {@link club.minnced.discord.webhook.send.WebhookMessageBuilder#addFile(MessageAttachment)}
* to retain existing attachments on a message for an edit request.
*
* @param id
* The snowflake ID for this attachment (must exist on the message you edit9
*
* @throws java.lang.IllegalArgumentException
* If the provided ID is not a valid snowflake
*
* @return The attachment instance
*/
@NotNull
public static MessageAttachment fromId(long id) {
return fromId(id, null);
}

@NotNull
public String getName() {
return name;
Expand All @@ -56,4 +112,18 @@ public String getName() {
public byte[] getData() {
return data;
}

public long getId() {
return id;
}

@NotNull
public JSONObject toJSON() {
JSONObject json = new JSONObject();
if (!name.isEmpty())
json.put("name", name);
if (id != 0)
json.put("id", id);
return json;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,33 @@ public static WebhookMessage embeds(@NotNull Collection<WebhookEmbed> embeds) {
return new WebhookMessage(null, null, null, new ArrayList<>(embeds), false, null, AllowedMentions.all(), 0);
}

/**
* Creates a WebhookMessage from the provided attachments.
* <br>A message can hold up to {@value #MAX_FILES} attachments
* and a total of 8MiB of data.
*
* @param attachments
* The attachments to add, keys are the alternative names
* for each attachment
*
* @throws java.lang.NullPointerException
* If provided with null
* @throws java.lang.IllegalArgumentException
* If no attachments are provided or more than {@value #MAX_FILES}
*
* @return A WebhookMessage for the attachments
*/
@NotNull
public static WebhookMessage files(@NotNull Collection<? extends MessageAttachment> attachments) {
Objects.requireNonNull(attachments, "Attachments");

int fileAmount = attachments.size();
if (fileAmount > WebhookMessage.MAX_FILES)
throw new IllegalArgumentException("Cannot add more than " + WebhookMessage.MAX_FILES + " files to a message");
MessageAttachment[] files = attachments.toArray(new MessageAttachment[0]);
return new WebhookMessage(null, null, null, null, false, files, AllowedMentions.all(), 0);
}

/**
* Creates a WebhookMessage from the provided attachments.
* <br>A message can hold up to {@value #MAX_FILES} attachments
Expand All @@ -254,8 +281,6 @@ public static WebhookMessage files(@NotNull Map<String, ?> attachments) {
Objects.requireNonNull(attachments, "Attachments");

int fileAmount = attachments.size();
if (fileAmount == 0)
throw new IllegalArgumentException("Cannot build an empty message");
if (fileAmount > WebhookMessage.MAX_FILES)
throw new IllegalArgumentException("Cannot add more than " + WebhookMessage.MAX_FILES + " files to a message");
Set<? extends Map.Entry<String, ?>> entries = attachments.entrySet();
Expand Down Expand Up @@ -351,19 +376,28 @@ public RequestBody getBody() {
payload.put("tts", isTTS);
payload.put("allowed_mentions", allowedMentions);
payload.put("flags", flags);
String json = payload.toString();
if (isFile()) {
final MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
JSONArray attachmentArray = new JSONArray(attachments.length);

for (int i = 0; i < attachments.length; i++) {
final MessageAttachment attachment = attachments[i];
if (attachment == null)
break;
builder.addFormDataPart("file" + i, attachment.getName(), new IOUtil.OctetBody(attachment.getData()));

JSONObject attachmentJson = attachment.toJSON();
if (attachment.getId() == 0) {
builder.addFormDataPart("files[" + i + "]", attachment.getName(), new IOUtil.OctetBody(attachment.getData()));
attachmentJson.put("id", i);
}

attachmentArray.put(attachmentJson);
}
return builder.addFormDataPart("payload_json", json).build();

payload.put("attachments", attachmentArray);
return builder.addFormDataPart("payload_json", payload.toString()).build();
}
return RequestBody.create(IOUtil.JSON, json);
return RequestBody.create(IOUtil.JSON, payload.toString());
}

@NotNull
Expand All @@ -372,7 +406,9 @@ private static MessageAttachment convertAttachment(@NotNull String name, @NotNul
Objects.requireNonNull(data, "Data");
try {
MessageAttachment a;
if (data instanceof File)
if (data instanceof MessageAttachment)
a = (MessageAttachment) data;
else if (data instanceof File)
a = new MessageAttachment(name, (File) data);
else if (data instanceof InputStream)
a = new MessageAttachment(name, (InputStream) data);
Expand Down
Loading