Merge jda-webhooks

This commit is contained in:
Vankka 2023-06-18 14:15:57 +03:00
commit 9fd3903550
No known key found for this signature in database
GPG Key ID: 6E50CB7A29B96AD0
20 changed files with 145 additions and 169 deletions

View File

@ -56,6 +56,14 @@ public interface DiscordUser extends JDAEntity<User>, Snowflake, Mentionable {
@NotNull
String getUsername();
/**
* Gets the effective display name of the Discord user.
* @return the user's effective display name
*/
@Placeholder("user_effective_name")
@NotNull
String getEffectiveName();
/**
* Gets the Discord user's discriminator.
* @return the user's discriminator
@ -85,7 +93,7 @@ public interface DiscordUser extends JDAEntity<User>, Snowflake, Mentionable {
* Gets the Discord user's username followed by a {@code #} and their discriminator.
* @return the Discord user's username and discriminator in the following format {@code Username#1234}
*/
@Placeholder("user_tag")
@Deprecated
default String getAsTag() {
return getUsername() + "#" + getDiscriminator();
}

View File

@ -29,6 +29,7 @@ import com.discordsrv.api.discord.entity.message.ReceivedDiscordMessage;
import com.discordsrv.api.discord.entity.message.SendableDiscordMessage;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.InputStream;
import java.util.Collections;
@ -86,7 +87,7 @@ public interface DiscordMessageChannel extends Snowflake {
* @return a future returning the message after being edited
*/
@NotNull
CompletableFuture<ReceivedDiscordMessage> editMessageById(long id, @NotNull SendableDiscordMessage message);
CompletableFuture<ReceivedDiscordMessage> editMessageById(long id, @NotNull SendableDiscordMessage message, @Nullable Map<String, InputStream> attachments);
/**
* Returns the JDA representation of this object. This should not be used if it can be avoided.

View File

@ -94,18 +94,18 @@ public interface DiscordGuildMember extends JDAEntity<Member>, Mentionable {
* Gets the effective name of this Discord server member.
* @return the Discord server member's effective name
*/
@Placeholder("user_effective_name")
@Placeholder("user_effective_server_name")
@NotNull
default String getEffectiveName() {
default String getEffectiveServerName() {
String nickname = getNickname();
return nickname != null ? nickname : getUser().getUsername();
return nickname != null ? nickname : getUser().getEffectiveName();
}
/**
* Gets the avatar url that is active for this user in this server.
* @return the user's avatar url in this server
*/
@Placeholder("user_effective_avatar_url")
@Placeholder("user_effective_server_avatar_url")
@NotNull
String getEffectiveServerAvatarUrl();

View File

@ -34,7 +34,9 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Unmodifiable;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
/**
@ -147,6 +149,10 @@ public interface ReceivedDiscordMessage extends Snowflake {
@NotNull
CompletableFuture<Void> delete();
default CompletableFuture<ReceivedDiscordMessage> edit(@NotNull SendableDiscordMessage message) {
return edit(message, null);
}
/**
* Edits this message to the provided message.
*
@ -156,7 +162,7 @@ public interface ReceivedDiscordMessage extends Snowflake {
* but the provided {@link SendableDiscordMessage} specifies a webhook username.
*/
@NotNull
CompletableFuture<ReceivedDiscordMessage> edit(SendableDiscordMessage message);
CompletableFuture<ReceivedDiscordMessage> edit(@NotNull SendableDiscordMessage message, @Nullable Map<String, InputStream> attachments);
class Attachment {

View File

@ -53,7 +53,8 @@ subprojects {
includeGroup 'me.scarsz'
includeGroup 'me.minecraftauth'
includeGroup 'org.spongepowered' // Configurate yamlbranch
includeGroup 'org.spongepowered' // SpongePowered/Configurate feature/yaml-improvements branch
includeGroup 'net.dv8tion' // DiscordSRV/JDA v5-webhooks branch
}
}
maven {

View File

@ -42,12 +42,6 @@ dependencies {
// DependencyDownload
api(libs.dependencydownload.runtime)
// Discord Webhooks
runtimeDownloadApi(libs.webhooks) {
// okhttp is already included
exclude group: 'com.squareup.okhttp3', module: 'okhttp'
}
// Apache Commons
runtimeDownloadApi(libs.commons.lang)
runtimeDownloadApi(libs.commons.io)

View File

@ -136,7 +136,7 @@ public class DebugCommand extends CombinedCommand {
String key = new String(KEY_ENCODER.encode(paste.decryptionKey()), StandardCharsets.UTF_8);
String url = String.format(URL_FORMAT, paste.id(), key);
execution.send(new Text(url));
execution.send(new Text(url)); // TODO: fix in-game click
return null;
} catch (Throwable e) {
return e;

View File

@ -34,11 +34,11 @@ public class DiscordToMinecraftChatConfig {
@Comment("The Discord to Minecraft message format for regular users and bots")
@Untranslated(Untranslated.Type.VALUE)
public String format = "[&#5865F2Discord&r] [hover:show_text:Tag: %user_tag%&r\nRoles: %user_roles:', '|text:'&7&oNone'%]%user_color%%user_effective_name%&r » %message%%message_attachments%";
public String format = "[&#5865F2Discord&r] [hover:show_text:Tag: %user_tag%&r\nRoles: %user_roles:', '|text:'&7&oNone'%]%user_color%%user_effective_server_name%&r » %message%%message_attachments%";
@Comment("The Discord to Minecraft message format for webhook messages (if enabled)")
@Untranslated(Untranslated.Type.VALUE)
public String webhookFormat = "[&#5865F2Discord&r] [hover:show_text:Bot message]%user_name%&r » %message%%message_attachments%";
public String webhookFormat = "[&#5865F2Discord&r] [hover:show_text:Bot message]%user_effective_name%&r » %message%%message_attachments%";
@Comment("Attachment format")
@Untranslated(Untranslated.Type.VALUE)
@ -60,7 +60,7 @@ public class DiscordToMinecraftChatConfig {
public Format role = new Format("&#5865f2@%role_name%", "&#5865f2@deleted-role");
public Format channel = new Format("[hover:show_text:Click to go to channel][click:open_url:%channel_jump_url%]&#5865f2#%channel_name%", "&#5865f2#Unknown");
public Format user = new Format("[hover:show_text:Tag: %user_tag%&r\nRoles: %user_roles:', '|text:'&7&oNone'%]&#5865f2@%user_effective_name|user_name%", "&#5865f2@Unknown user");
public Format user = new Format("[hover:show_text:Username: @%user_name%&r\nRoles: %user_roles:', '|text:'&7&oNone'%]&#5865f2@%user_effective_server_name|user_effective_name%", "&#5865f2@Unknown user");
public String messageUrl = "[hover:show_text:Click to go to message][click:open_url:%jump_url%]&#5865f2#%channel_name% > ...";

View File

@ -33,12 +33,12 @@ public class MirroringConfig {
@Comment("The format of the username of mirrored messages\n"
+ "It's recommended to include some special character if in-game messages use webhooks,\n"
+ "in order to prevent Discord users and in-game players with the same name being grouped together")
public String usernameFormat = "%user_effective_name% \uD83D\uDD03";
public String usernameFormat = "%user_effective_server_name|user_effective_name% \uD83D\uDD03";
@Comment("The format when a message is a reply.\n"
+ "%message% will be replaced with the message content\n"
+ "%message_jump_url% will be replaced with the url to the replied message in the channel the message is sent in")
public String replyFormat = "[In reply to %user_effective_name|user_name%](%message_jump_url%)\n%message%";
public String replyFormat = "[In reply to %user_effective_server_name|user_effective_name%](%message_jump_url%)\n%message%";
@Comment("Attachment related options")
public AttachmentConfig attachments = new AttachmentConfig();

View File

@ -18,8 +18,6 @@
package com.discordsrv.common.discord.api;
import club.minnced.discord.webhook.WebhookClient;
import club.minnced.discord.webhook.WebhookClientBuilder;
import com.discordsrv.api.discord.DiscordAPI;
import com.discordsrv.api.discord.connection.details.DiscordGatewayIntent;
import com.discordsrv.api.discord.connection.jda.errorresponse.ErrorCallbackContext;
@ -70,7 +68,7 @@ public class DiscordAPIImpl implements DiscordAPI {
private final DiscordSRV discordSRV;
private final DiscordCommandRegistry commandRegistry;
private final AsyncLoadingCache<Long, WebhookClient> cachedClients;
private final AsyncLoadingCache<Long, WebhookClient<Message>> cachedClients;
private final List<ThreadChannelLookup> threadLookups = new CopyOnWriteArrayList<>();
public DiscordAPIImpl(DiscordSRV discordSRV) {
@ -81,11 +79,11 @@ public class DiscordAPIImpl implements DiscordAPI {
.buildAsync(new WebhookCacheLoader());
}
public CompletableFuture<WebhookClient> queryWebhookClient(long channelId) {
public CompletableFuture<WebhookClient<Message>> queryWebhookClient(long channelId) {
return cachedClients.get(channelId);
}
public AsyncLoadingCache<Long, WebhookClient> getCachedClients() {
public AsyncLoadingCache<Long, WebhookClient<Message>> getCachedClients() {
return cachedClients;
}
@ -503,10 +501,10 @@ public class DiscordAPIImpl implements DiscordAPI {
return commandRegistry;
}
private class WebhookCacheLoader implements AsyncCacheLoader<Long, WebhookClient> {
private class WebhookCacheLoader implements AsyncCacheLoader<Long, WebhookClient<Message>> {
@Override
public @NonNull CompletableFuture<WebhookClient> asyncLoad(@NonNull Long channelId, @NonNull Executor executor) {
public @NonNull CompletableFuture<WebhookClient<Message>> asyncLoad(@NonNull Long channelId, @NonNull Executor executor) {
JDA jda = discordSRV.jda();
if (jda == null) {
return notReady();
@ -539,15 +537,16 @@ public class DiscordAPIImpl implements DiscordAPI {
return textChannel.createWebhook("DSRV").submit();
}).thenApply(webhook ->
WebhookClientBuilder.fromJDA(webhook)
.setHttpClient(jda.getHttpClient())
.setExecutorService(discordSRV.scheduler().scheduledExecutorService())
.build()
WebhookClient.createClient(
webhook.getJDA(),
webhook.getId(),
Objects.requireNonNull(webhook.getToken())
)
);
}
}
private class WebhookCacheExpiry implements Expiry<Long, WebhookClient> {
private class WebhookCacheExpiry implements Expiry<Long, WebhookClient<Message>> {
private boolean isConfiguredChannel(Long channelId) {
for (BaseChannelConfig config : discordSRV.config().channels.values()) {

View File

@ -61,6 +61,11 @@ public class DiscordUserImpl implements DiscordUser {
return user.getName();
}
@Override
public @NotNull String getEffectiveName() {
return user.getEffectiveName();
}
@Override
public @NotNull String getDiscriminator() {
return user.getDiscriminator();

View File

@ -18,9 +18,6 @@
package com.discordsrv.common.discord.api.entity.channel;
import club.minnced.discord.webhook.WebhookClient;
import club.minnced.discord.webhook.receive.ReadonlyMessage;
import club.minnced.discord.webhook.send.WebhookMessageBuilder;
import com.discordsrv.api.discord.entity.channel.DiscordGuildMessageChannel;
import com.discordsrv.api.discord.entity.guild.DiscordGuild;
import com.discordsrv.api.discord.entity.message.ReceivedDiscordMessage;
@ -29,16 +26,22 @@ import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.discord.api.entity.message.ReceivedDiscordMessageImpl;
import com.discordsrv.common.discord.api.entity.message.util.SendableDiscordMessageUtil;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.WebhookClient;
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
import net.dv8tion.jda.api.requests.FluentRestAction;
import net.dv8tion.jda.api.requests.restaction.MessageCreateAction;
import net.dv8tion.jda.api.requests.RestAction;
import net.dv8tion.jda.api.utils.FileUpload;
import net.dv8tion.jda.api.utils.messages.MessageCreateData;
import net.dv8tion.jda.api.utils.messages.MessageCreateRequest;
import net.dv8tion.jda.api.utils.messages.MessageEditData;
import net.dv8tion.jda.api.utils.messages.MessageEditRequest;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
public abstract class AbstractDiscordGuildMessageChannel<T extends GuildMessageChannel>
extends AbstractDiscordMessageChannel<T>
@ -51,7 +54,7 @@ public abstract class AbstractDiscordGuildMessageChannel<T extends GuildMessageC
this.guild = discordSRV.discordAPI().getGuild(channel.getGuild());
}
public CompletableFuture<WebhookClient> queryWebhookClient() {
public CompletableFuture<WebhookClient<Message>> queryWebhookClient() {
return discordSRV.discordAPI().queryWebhookClient(getId());
}
@ -79,48 +82,75 @@ public abstract class AbstractDiscordGuildMessageChannel<T extends GuildMessageC
public CompletableFuture<ReceivedDiscordMessage> sendMessage(
@NotNull SendableDiscordMessage message, @NotNull Map<String, InputStream> attachments
) {
return message(message, (webhookClient, webhookMessage) -> {
for (Map.Entry<String, InputStream> entry : attachments.entrySet()) {
webhookMessage.addFile(entry.getKey(), entry.getValue());
}
return webhookClient.send(webhookMessage.build());
}, (channel, msg) -> {
MessageCreateAction action = channel.sendMessage(SendableDiscordMessageUtil.toJDASend(msg));
for (Map.Entry<String, InputStream> entry : attachments.entrySet()) {
action = action.addFiles(FileUpload.fromData(entry.getValue(), entry.getKey()));
}
return action;
});
return sendInternal(message, attachments);
}
@SuppressWarnings("unchecked") // Generics
private <R extends MessageCreateRequest<? extends MessageCreateRequest<?>> & RestAction<Message>> CompletableFuture<ReceivedDiscordMessage> sendInternal(SendableDiscordMessage message, Map<String, InputStream> attachments) {
MessageCreateData createData = SendableDiscordMessageUtil.toJDASend(message);
CompletableFuture<R> createRequest;
if (message.isWebhookMessage()) {
createRequest = queryWebhookClient()
.thenApply(client -> (R) client.sendMessage(createData)
.setUsername(message.getWebhookUsername())
.setAvatarUrl(message.getWebhookAvatarUrl())
);
} else {
createRequest = CompletableFuture.completedFuture(((R) channel.sendMessage(createData)));
}
return createRequest
.thenApply(action -> {
for (Map.Entry<String, InputStream> entry : attachments.entrySet()) {
action = (R) action.addFiles(FileUpload.fromData(entry.getValue(), entry.getKey()));
}
return action;
})
.thenCompose(RestAction::submit)
.thenApply(msg -> ReceivedDiscordMessageImpl.fromJDA(discordSRV, msg));
}
@Override
public @NotNull CompletableFuture<ReceivedDiscordMessage> editMessageById(long id, @NotNull SendableDiscordMessage message) {
return message(
message,
(client, msg) -> client.edit(id, msg.build()),
(textChannel, msg) -> textChannel.editMessageById(id, SendableDiscordMessageUtil.toJDAEdit(msg))
);
public @NotNull CompletableFuture<ReceivedDiscordMessage> editMessageById(
long id,
@NotNull SendableDiscordMessage message,
@Nullable Map<String, InputStream> attachments
) {
return editInternal(id, message, attachments);
}
private CompletableFuture<ReceivedDiscordMessage> message(
@SuppressWarnings("unchecked") // Generics
private <R extends MessageEditRequest<? extends MessageEditRequest<?>> & RestAction<Message>> CompletableFuture<ReceivedDiscordMessage> editInternal(
long id,
SendableDiscordMessage message,
BiFunction<WebhookClient, WebhookMessageBuilder, CompletableFuture<ReadonlyMessage>> webhookFunction,
BiFunction<T, SendableDiscordMessage, FluentRestAction<? extends Message, ?>> jdaFunction) {
return discordSRV.discordAPI().mapExceptions(() -> {
CompletableFuture<ReceivedDiscordMessage> future;
if (message.isWebhookMessage()) {
future = queryWebhookClient()
.thenCompose(client -> webhookFunction.apply(
client, SendableDiscordMessageUtil.toWebhook(message)))
.thenApply(msg -> ReceivedDiscordMessageImpl.fromWebhook(discordSRV, msg));
} else {
future = jdaFunction
.apply(channel, message)
.submit()
.thenApply(msg -> ReceivedDiscordMessageImpl.fromJDA(discordSRV, msg));
}
return future;
});
Map<String, InputStream> attachments
) {
MessageEditData editData = SendableDiscordMessageUtil.toJDAEdit(message);
CompletableFuture<R> editRequest;
if (message.isWebhookMessage()) {
editRequest = queryWebhookClient().thenApply(client -> (R) client.editMessageById(id, editData));
} else {
editRequest = CompletableFuture.completedFuture(((R) channel.editMessageById(id, editData)));
}
return editRequest
.thenApply(action -> {
if (attachments != null) {
List<FileUpload> uploads = new ArrayList<>();
for (Map.Entry<String, InputStream> entry : attachments.entrySet()) {
uploads.add(FileUpload.fromData(entry.getValue(), entry.getKey()));
}
action = (R) action.setFiles(uploads);
} else {
action = (R) action.setAttachments(); // TODO
}
return action;
})
.thenCompose(RestAction::submit)
.thenApply(msg -> ReceivedDiscordMessageImpl.fromJDA(discordSRV, msg));
}
@Override
@ -131,7 +161,7 @@ public abstract class AbstractDiscordGuildMessageChannel<T extends GuildMessageC
} else {
future = discordSRV.discordAPI()
.queryWebhookClient(channel.getIdLong())
.thenCompose(client -> client.delete(id));
.thenCompose(client -> client.deleteMessageById(id).submit());
}
return discordSRV.discordAPI().mapExceptions(future);
}

View File

@ -30,6 +30,7 @@ import net.dv8tion.jda.api.entities.channel.concrete.PrivateChannel;
import net.dv8tion.jda.api.requests.restaction.MessageCreateAction;
import net.dv8tion.jda.api.utils.FileUpload;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.InputStream;
import java.util.Map;
@ -80,7 +81,11 @@ public class DiscordDMChannelImpl extends AbstractDiscordMessageChannel<PrivateC
}
@Override
public @NotNull CompletableFuture<ReceivedDiscordMessage> editMessageById(long id, @NotNull SendableDiscordMessage message) {
public @NotNull CompletableFuture<ReceivedDiscordMessage> editMessageById(
long id,
@NotNull SendableDiscordMessage message,
@Nullable Map<String, InputStream> attachments
) {
if (message.isWebhookMessage()) {
throw new IllegalArgumentException("Cannot send webhook messages to DMChannels");
}

View File

@ -18,16 +18,18 @@
package com.discordsrv.common.discord.api.entity.channel;
import club.minnced.discord.webhook.WebhookClient;
import com.discordsrv.api.discord.entity.channel.DiscordChannelType;
import com.discordsrv.api.discord.entity.channel.DiscordThreadChannel;
import com.discordsrv.api.discord.entity.channel.DiscordThreadContainer;
import com.discordsrv.api.discord.entity.guild.DiscordGuild;
import com.discordsrv.common.DiscordSRV;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.WebhookClient;
import net.dv8tion.jda.api.entities.channel.ChannelType;
import net.dv8tion.jda.api.entities.channel.attribute.IThreadContainer;
import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.internal.requests.IncomingWebhookClient;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.CompletableFuture;
@ -48,10 +50,10 @@ public class DiscordThreadChannelImpl extends AbstractDiscordGuildMessageChannel
}
@Override
public CompletableFuture<WebhookClient> queryWebhookClient() {
public CompletableFuture<WebhookClient<Message>> queryWebhookClient() {
return discordSRV.discordAPI()
.queryWebhookClient(getParentChannel().getId())
.thenApply(client -> client.onThread(getId()));
.thenApply(client -> ((IncomingWebhookClient) client).withThreadId(Long.toUnsignedString(getId())));
}
@Override

View File

@ -54,7 +54,7 @@ public class ReceivedDiscordMessageClusterImpl implements ReceivedDiscordMessage
public @NotNull CompletableFuture<ReceivedDiscordMessageCluster> editAll(SendableDiscordMessage newMessage) {
List<CompletableFuture<ReceivedDiscordMessage>> futures = new ArrayList<>(messages.size());
for (ReceivedDiscordMessage message : messages) {
futures.add(message.edit(newMessage));
futures.add(message.edit(newMessage, null));
}
return CompletableFutureUtil.combine(futures).thenApply(ReceivedDiscordMessageClusterImpl::new);

View File

@ -18,12 +18,6 @@
package com.discordsrv.common.discord.api.entity.message;
import club.minnced.discord.webhook.WebhookClient;
import club.minnced.discord.webhook.receive.ReadonlyAttachment;
import club.minnced.discord.webhook.receive.ReadonlyEmbed;
import club.minnced.discord.webhook.receive.ReadonlyMessage;
import club.minnced.discord.webhook.send.WebhookEmbed;
import com.discordsrv.api.color.Color;
import com.discordsrv.api.discord.entity.DiscordUser;
import com.discordsrv.api.discord.entity.channel.DiscordDMChannel;
import com.discordsrv.api.discord.entity.channel.DiscordMessageChannel;
@ -44,14 +38,17 @@ import com.discordsrv.common.future.util.CompletableFutureUtil;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.WebhookClient;
import net.dv8tion.jda.api.requests.ErrorResponse;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Unmodifiable;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
public class ReceivedDiscordMessageImpl implements ReceivedDiscordMessage {
@ -71,7 +68,7 @@ public class ReceivedDiscordMessageImpl implements ReceivedDiscordMessage {
boolean self = false;
if (webhookMessage) {
CompletableFuture<WebhookClient> clientFuture = discordSRV.discordAPI()
CompletableFuture<WebhookClient<Message>> clientFuture = discordSRV.discordAPI()
.getCachedClients()
.getIfPresent(channel instanceof DiscordThreadChannel
? ((DiscordThreadChannel) channel).getParentChannel().getId()
@ -79,7 +76,7 @@ public class ReceivedDiscordMessageImpl implements ReceivedDiscordMessage {
);
if (clientFuture != null) {
long clientId = clientFuture.join().getId();
long clientId = clientFuture.join().getIdLong();
self = clientId == user.getId();
}
} else {
@ -113,71 +110,6 @@ public class ReceivedDiscordMessageImpl implements ReceivedDiscordMessage {
);
}
public static ReceivedDiscordMessage fromWebhook(DiscordSRV discordSRV, ReadonlyMessage webhookMessage) {
List<DiscordMessageEmbed> mappedEmbeds = new ArrayList<>();
for (ReadonlyEmbed embed : webhookMessage.getEmbeds()) {
List<DiscordMessageEmbed.Field> fields = new ArrayList<>();
for (WebhookEmbed.EmbedField field : embed.getFields()) {
fields.add(new DiscordMessageEmbed.Field(field.getName(), field.getValue(), field.isInline()));
}
Integer color = embed.getColor();
WebhookEmbed.EmbedAuthor author = embed.getAuthor();
WebhookEmbed.EmbedTitle title = embed.getTitle();
ReadonlyEmbed.EmbedImage thumbnail = embed.getThumbnail();
ReadonlyEmbed.EmbedImage image = embed.getImage();
WebhookEmbed.EmbedFooter footer = embed.getFooter();
mappedEmbeds.add(new DiscordMessageEmbed(
color != null ? new Color(color) : null,
author != null ? author.getName() : null,
author != null ? author.getUrl() : null,
author != null ? author.getIconUrl() : null,
title != null ? title.getText() : null,
title != null ? title.getUrl() : null,
embed.getDescription(),
fields,
thumbnail != null ? thumbnail.getUrl() : null,
image != null ? image.getUrl() : null,
embed.getTimestamp(),
footer != null ? footer.getText() : null,
footer != null ? footer.getIconUrl() : null
));
}
DiscordMessageChannel channel = discordSRV.discordAPI().getMessageChannelById(
webhookMessage.getChannelId());
DiscordUser user = discordSRV.discordAPI().getUserById(
webhookMessage.getAuthor().getId());
DiscordGuildMember member = channel instanceof DiscordTextChannel && user != null
? ((DiscordTextChannel) channel).getGuild().getMemberById(user.getId()) : null;
List<Attachment> attachments = new ArrayList<>();
for (ReadonlyAttachment attachment : webhookMessage.getAttachments()) {
attachments.add(new Attachment(
attachment.getFileName(),
attachment.getUrl(),
attachment.getProxyUrl(),
attachment.getSize()
));
}
return new ReceivedDiscordMessageImpl(
discordSRV,
attachments,
true, // These are always from rest responses
channel,
null,
member,
user,
webhookMessage.getChannelId(),
webhookMessage.getId(),
webhookMessage.getContent(),
mappedEmbeds,
true
);
}
private final DiscordSRV discordSRV;
private final List<Attachment> attachments;
private final boolean fromSelf;
@ -305,7 +237,10 @@ public class ReceivedDiscordMessageImpl implements ReceivedDiscordMessage {
}
@Override
public @NotNull CompletableFuture<ReceivedDiscordMessage> edit(SendableDiscordMessage message) {
public @NotNull CompletableFuture<ReceivedDiscordMessage> edit(
@NotNull SendableDiscordMessage message,
@Nullable Map<String, InputStream> attachments
) {
if (!webhookMessage && message.isWebhookMessage()) {
throw new IllegalArgumentException("Cannot edit a non-webhook message into a webhook message");
}
@ -315,7 +250,7 @@ public class ReceivedDiscordMessageImpl implements ReceivedDiscordMessage {
return CompletableFutureUtil.failed(new RestErrorResponseException(ErrorResponse.UNKNOWN_CHANNEL));
}
return textChannel.editMessageById(getId(), message);
return textChannel.editMessageById(getId(), message, attachments);
}
//

View File

@ -18,7 +18,6 @@
package com.discordsrv.common.discord.api.entity.message.util;
import club.minnced.discord.webhook.send.WebhookMessageBuilder;
import com.discordsrv.api.discord.entity.interaction.component.actionrow.MessageActionRow;
import com.discordsrv.api.discord.entity.message.AllowedMention;
import com.discordsrv.api.discord.entity.message.DiscordMessageEmbed;
@ -91,10 +90,4 @@ public final class SendableDiscordMessageUtil {
.setComponents(actionRows)
.build();
}
public static WebhookMessageBuilder toWebhook(@NotNull SendableDiscordMessage message) {
return WebhookMessageBuilder.fromJDA(null/*toJDA(message)*/) // TODO: lib update? lib replacement?
.setUsername(message.getWebhookUsername())
.setAvatarUrl(message.getWebhookAvatarUrl());
}
}

View File

@ -642,7 +642,7 @@ public class JDAConnectionManager implements DiscordConnectionManager {
discordSRV.logger().error("| server requiring 2FA for moderation actions");
if (user != null) {
discordSRV.logger().error("|");
discordSRV.logger().error("| The Discord bot's owner is " + user.getAsTag() + " (" + user.getId() + ")");
discordSRV.logger().error("| The Discord bot's owner is " + user.getUsername() + " (" + user.getId() + ")");
}
discordSRV.logger().error("|");
discordSRV.logger().error("| You can view instructions for enabling 2FA here:");

View File

@ -231,7 +231,7 @@ public class DiscordMessageMirroringModule extends AbstractModule<DiscordSRV> {
}
SendableDiscordMessage sendableMessage = convert(message, channel, reference.config).build();
channel.editMessageById(reference.messageId, sendableMessage).whenComplete((v, t) -> {
channel.editMessageById(reference.messageId, sendableMessage, null).whenComplete((v, t) -> {
if (t != null) {
discordSRV.logger().error("Failed to update mirrored message in " + channel);
}

View File

@ -56,15 +56,12 @@ dependencyResolutionManagement {
library('findbugs-annotations', 'com.google.code.findbugs', 'jsr305').version('3.0.2')
// JDA
library('jda', 'net.dv8tion', 'JDA').version('5.0.0-beta.9')
library('jda', 'net.dv8tion', 'JDA').version('5.0.0-beta.10.webhooks_2')
library('okhttp', 'com.squareup.okhttp3', 'okhttp').version {
prefer '3.14.9'
reject '[4,)' // Kotlin
}
// Discord Webhooks
library('webhooks', 'club.minnced', 'discord-webhooks').version('0.8.2')
// Apache commons
library('commons-lang', 'org.apache.commons', 'commons-lang3').version('3.12.0')
library('commons-io', 'commons-io', 'commons-io').version('2.11.0')