Refactor Discord message sending to use MessageForEmbed object and add support for creating threads in targeted channels.
This commit is contained in:
parent
ec3435dccc
commit
0f11167953
|
|
@ -9,6 +9,7 @@ import com.alttd.altitudeweb.database.litebans.HistoryType;
|
||||||
import com.alttd.altitudeweb.database.litebans.UserType;
|
import com.alttd.altitudeweb.database.litebans.UserType;
|
||||||
import com.alttd.altitudeweb.database.web_db.forms.Appeal;
|
import com.alttd.altitudeweb.database.web_db.forms.Appeal;
|
||||||
import com.alttd.altitudeweb.setup.Connection;
|
import com.alttd.altitudeweb.setup.Connection;
|
||||||
|
import com.alttd.webinterface.objects.MessageForEmbed;
|
||||||
import com.alttd.webinterface.send_message.DiscordSender;
|
import com.alttd.webinterface.send_message.DiscordSender;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
@ -97,15 +98,9 @@ public class AppealDiscord {
|
||||||
|
|
||||||
// colorRgb = null (use default), timestamp = appeal.createdAt if available
|
// colorRgb = null (use default), timestamp = appeal.createdAt if available
|
||||||
Instant timestamp = appeal.createdAt() != null ? appeal.createdAt() : Instant.now();
|
Instant timestamp = appeal.createdAt() != null ? appeal.createdAt() : Instant.now();
|
||||||
DiscordSender.getInstance().sendEmbedToChannels(
|
MessageForEmbed newAppealSubmitted = new MessageForEmbed(
|
||||||
channelIds,
|
"New Appeal Submitted", description, fields, null, timestamp, null);
|
||||||
"New Appeal Submitted",
|
DiscordSender.getInstance().sendEmbedWithThreadToChannels(channelIds, newAppealSubmitted, "Appeal");
|
||||||
description,
|
|
||||||
fields,
|
|
||||||
null,
|
|
||||||
timestamp,
|
|
||||||
null
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompletableFuture<Integer> getCountAsync(HistoryType type, java.util.UUID uuid) {
|
private CompletableFuture<Integer> getCountAsync(HistoryType type, java.util.UUID uuid) {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import com.alttd.altitudeweb.database.discord.OutputChannel;
|
||||||
import com.alttd.altitudeweb.database.discord.OutputChannelMapper;
|
import com.alttd.altitudeweb.database.discord.OutputChannelMapper;
|
||||||
import com.alttd.altitudeweb.database.web_db.forms.StaffApplication;
|
import com.alttd.altitudeweb.database.web_db.forms.StaffApplication;
|
||||||
import com.alttd.altitudeweb.setup.Connection;
|
import com.alttd.altitudeweb.setup.Connection;
|
||||||
|
import com.alttd.webinterface.objects.MessageForEmbed;
|
||||||
import com.alttd.webinterface.send_message.DiscordSender;
|
import com.alttd.webinterface.send_message.DiscordSender;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
@ -79,16 +80,15 @@ public class StaffApplicationDiscord {
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
Instant timestamp = application.createdAt() != null ? application.createdAt() : Instant.now();
|
Instant timestamp = application.createdAt() != null ? application.createdAt() : Instant.now();
|
||||||
DiscordSender.getInstance().sendEmbedToChannels(
|
MessageForEmbed messageForEmbed = new MessageForEmbed(
|
||||||
channelIds,
|
|
||||||
"New Staff Application Submitted",
|
"New Staff Application Submitted",
|
||||||
"Join date: " + (application.joinDate() != null ? application.joinDate().toString() : "unknown") +
|
"Join date: " + (application.joinDate() != null ? application.joinDate().toString() : "unknown") +
|
||||||
"\nSubmitted: " + formatInstant(timestamp),
|
"\nSubmitted: " + formatInstant(timestamp),
|
||||||
fields,
|
fields,
|
||||||
null,
|
null,
|
||||||
timestamp,
|
timestamp,
|
||||||
null
|
null);
|
||||||
);
|
DiscordSender.getInstance().sendEmbedWithThreadToChannels(channelIds, messageForEmbed, "Staff Application");
|
||||||
}
|
}
|
||||||
|
|
||||||
private String safe(String s) {
|
private String safe(String s) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.alttd.webinterface.objects;
|
||||||
|
|
||||||
|
import com.alttd.webinterface.send_message.DiscordSender;
|
||||||
|
import net.dv8tion.jda.api.EmbedBuilder;
|
||||||
|
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record MessageForEmbed(String title, String description, List<DiscordSender.EmbedField> fields, Integer colorRgb,
|
||||||
|
Instant timestamp, String footer) {
|
||||||
|
|
||||||
|
public MessageEmbed toEmbed() {
|
||||||
|
EmbedBuilder eb = new EmbedBuilder();
|
||||||
|
if (title != null && !title.isBlank()) {
|
||||||
|
eb.setTitle(title);
|
||||||
|
}
|
||||||
|
if (description != null && !description.isBlank()) {
|
||||||
|
eb.setDescription(description);
|
||||||
|
}
|
||||||
|
if (colorRgb != null) {
|
||||||
|
eb.setColor(new Color(colorRgb));
|
||||||
|
} else {
|
||||||
|
eb.setColor(new Color(0xFF8C00)); // default orange
|
||||||
|
}
|
||||||
|
eb.setTimestamp(timestamp != null ? timestamp : Instant.now());
|
||||||
|
if (footer != null && !footer.isBlank()) {
|
||||||
|
eb.setFooter(footer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fields != null) {
|
||||||
|
for (DiscordSender.EmbedField f : fields) {
|
||||||
|
if (f == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String name = f.getName() == null ? "" : f.getName();
|
||||||
|
String value = f.getValue() == null ? "" : f.getValue();
|
||||||
|
// JDA field value max is 1024; truncate to be safe
|
||||||
|
if (value.length() > 1024) {
|
||||||
|
value = value.substring(0, 1021) + "...";
|
||||||
|
}
|
||||||
|
eb.addField(new MessageEmbed.Field(name, value, f.isInline()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return eb.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,19 +1,21 @@
|
||||||
package com.alttd.webinterface.send_message;
|
package com.alttd.webinterface.send_message;
|
||||||
|
|
||||||
import com.alttd.webinterface.bot.DiscordBotInstance;
|
import com.alttd.webinterface.bot.DiscordBotInstance;
|
||||||
|
import com.alttd.webinterface.objects.MessageForEmbed;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.dv8tion.jda.api.EmbedBuilder;
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.util.ArrayList;
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class DiscordSender {
|
public class DiscordSender {
|
||||||
|
|
@ -70,12 +72,38 @@ public class DiscordSender {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendEmbedToChannels(List<Long> channelIds, String title, String description, List<EmbedField> fields,
|
public void sendEmbedWithThreadToChannels(List<Long> channelIds, MessageForEmbed messageForEmbed, String threadName) {
|
||||||
Integer colorRgb, Instant timestamp, String footer) {
|
sendEmbedToChannels(channelIds, messageForEmbed).whenCompleteAsync((result, error) -> {
|
||||||
|
if (error != null) {
|
||||||
|
log.error("Failed sending embed to channels", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
result.stream()
|
||||||
|
.filter(Optional::isPresent)
|
||||||
|
.map(Optional::get)
|
||||||
|
.forEach(message -> {
|
||||||
|
message.createThreadChannel(threadName).queue();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompletableFuture<List<Optional<Message>>> sendEmbedToChannels(List<Long> channelIds, MessageForEmbed messageForEmbed) {
|
||||||
|
List<CompletableFuture<Optional<Message>>> futures = new ArrayList<>();
|
||||||
|
for (Long channelId : channelIds) {
|
||||||
|
futures.add(sendEmbedToChannel(channelId, messageForEmbed));
|
||||||
|
}
|
||||||
|
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
|
||||||
|
.thenApply(v ->
|
||||||
|
futures.stream()
|
||||||
|
.map(CompletableFuture::join)
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompletableFuture<Optional<Message>> sendEmbedToChannel(Long channelId, MessageForEmbed messageForEmbed) {
|
||||||
ensureStarted();
|
ensureStarted();
|
||||||
if (botInstance.getJda() == null) {
|
if (botInstance.getJda() == null) {
|
||||||
log.error("JDA not initialized; cannot send Discord embed.");
|
log.error("JDA not initialized; cannot send Discord embed.");
|
||||||
return;
|
return CompletableFuture.completedFuture(Optional.empty());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (!botInstance.isReady()) {
|
if (!botInstance.isReady()) {
|
||||||
|
|
@ -83,43 +111,31 @@ public class DiscordSender {
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
|
return CompletableFuture.completedFuture(Optional.empty());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.warn("Error while waiting for JDA ready state", e);
|
log.warn("Error while waiting for JDA ready state", e);
|
||||||
|
return CompletableFuture.completedFuture(Optional.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
EmbedBuilder eb = new EmbedBuilder();
|
MessageEmbed embed = messageForEmbed.toEmbed();
|
||||||
if (title != null && !title.isBlank()) eb.setTitle(title);
|
|
||||||
if (description != null && !description.isBlank()) eb.setDescription(description);
|
|
||||||
if (colorRgb != null) eb.setColor(new Color(colorRgb)); else eb.setColor(new Color(0xFF8C00)); // default orange
|
|
||||||
eb.setTimestamp(timestamp != null ? timestamp : Instant.now());
|
|
||||||
if (footer != null && !footer.isBlank()) eb.setFooter(footer);
|
|
||||||
|
|
||||||
if (fields != null) {
|
TextChannel channel = botInstance.getJda().getChannelById(TextChannel.class, channelId);
|
||||||
for (EmbedField f : fields) {
|
if (channel == null) {
|
||||||
if (f == null) continue;
|
log.warn("TextChannel with id {} not found when sending embed message", channelId);
|
||||||
String name = f.getName() == null ? "" : f.getName();
|
return CompletableFuture.completedFuture(Optional.empty());
|
||||||
String value = f.getValue() == null ? "" : f.getValue();
|
|
||||||
// JDA field value max is 1024; truncate to be safe
|
|
||||||
if (value.length() > 1024) value = value.substring(0, 1021) + "...";
|
|
||||||
eb.addField(new MessageEmbed.Field(name, value, f.isInline()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
CompletableFuture<Optional<Message>> completableFuture = new CompletableFuture<>();
|
||||||
MessageEmbed embed = eb.build();
|
channel.sendMessageEmbeds(embed).queue(
|
||||||
|
message -> {
|
||||||
channelIds.stream()
|
completableFuture.complete(Optional.of(message));
|
||||||
.filter(Objects::nonNull)
|
log.debug("Sent embed to channel {}", channelId);
|
||||||
.forEach(id -> {
|
},
|
||||||
TextChannel channel = botInstance.getJda().getChannelById(TextChannel.class, id);
|
error -> {
|
||||||
if (channel == null) {
|
completableFuture.complete(Optional.empty());
|
||||||
log.warn("TextChannel with id {} not found", id);
|
log.error("Failed sending embed to channel {}", channelId, error);
|
||||||
return;
|
}
|
||||||
}
|
);
|
||||||
channel.sendMessageEmbeds(embed).queue(
|
return completableFuture;
|
||||||
success -> log.debug("Sent embed to channel {}", id),
|
|
||||||
error -> log.error("Failed sending embed to channel {}", id, error)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user