Merge pull request 'Fix CouncilChannel' (#384) from VelocityCore/FixDiscordBot into main

Reviewed-on: SteamWar/SteamWar#384
This commit is contained in:
2026-05-21 11:23:06 +02:00
4 changed files with 93 additions and 37 deletions
@@ -25,6 +25,7 @@ import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.dao.id.IntIdTable import org.jetbrains.exposed.v1.core.dao.id.IntIdTable
import org.jetbrains.exposed.v1.core.eq import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.core.inList import org.jetbrains.exposed.v1.core.inList
import org.jetbrains.exposed.v1.core.neq
import org.jetbrains.exposed.v1.dao.IntEntity import org.jetbrains.exposed.v1.dao.IntEntity
import org.jetbrains.exposed.v1.dao.IntEntityClass import org.jetbrains.exposed.v1.dao.IntEntityClass
import org.jetbrains.exposed.v1.jdbc.insert import org.jetbrains.exposed.v1.jdbc.insert
@@ -136,6 +137,12 @@ class SteamwarUser(id: EntityID<Int>) : IntEntity(id) {
.select(SteamwarUserTable.fields).where { UserPermTable.perm eq perm }.map { wrapRow(it) } .select(SteamwarUserTable.fields).where { UserPermTable.perm eq perm }.map { wrapRow(it) }
} }
@JvmStatic
fun getUsersWithDiscordId() =
useDb {
find { SteamwarUserTable.discordId neq null }.toList()
}
@JvmStatic @JvmStatic
fun getServerTeam() = fun getServerTeam() =
useDb { useDb {
@@ -22,6 +22,7 @@ package de.steamwar.velocitycore.discord;
import de.steamwar.command.SWCommand; import de.steamwar.command.SWCommand;
import de.steamwar.messages.Chatter; import de.steamwar.messages.Chatter;
import de.steamwar.sql.Event; import de.steamwar.sql.Event;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.velocitycore.VelocityCore; import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.velocitycore.discord.channels.*; import de.steamwar.velocitycore.discord.channels.*;
import de.steamwar.velocitycore.discord.listeners.ChannelListener; import de.steamwar.velocitycore.discord.listeners.ChannelListener;
@@ -52,12 +53,12 @@ import net.dv8tion.jda.api.utils.MemberCachePolicy;
import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
import java.awt.*; import java.awt.*;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Collectors;
public class DiscordBot { public class DiscordBot {
public static final String ARGUMENT_NAME = "arguments"; public static final String ARGUMENT_NAME = "arguments";
@@ -169,7 +170,7 @@ public class DiscordBot {
eventChannel = new StaticMessageChannel(config.channel("events"), EventChannel::get); eventChannel = new StaticMessageChannel(config.channel("events"), EventChannel::get);
checklistChannel = new ChecklistChannel(config.channel("checklist")); checklistChannel = new ChecklistChannel(config.channel("checklist"));
config.getCouncilThread().forEach((roleId, threadId) -> new CouncilChannel(DiscordBot.getGuild().getRoleById(roleId), DiscordBot.getGuild().getThreadChannelById(threadId))); CouncilChannel.initCouncilChannels();
announcementChannel = new DiscordChannel(config.channel("announcement"), 0) { announcementChannel = new DiscordChannel(config.channel("announcement"), 0) {
@Override @Override
@@ -20,47 +20,97 @@
package de.steamwar.velocitycore.discord.channels; package de.steamwar.velocitycore.discord.channels;
import de.steamwar.sql.SteamwarUser; import de.steamwar.sql.SteamwarUser;
import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.velocitycore.discord.DiscordBot; import de.steamwar.velocitycore.discord.DiscordBot;
import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel;
import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
public class CouncilChannel extends StaticMessageChannel { public class CouncilChannel extends StaticMessageChannel {
private static final Set<CouncilChannel> channels = new HashSet<>(); private static final Set<CouncilChannel> channels = new HashSet<>();
private static final Set<Role> roleSet = DiscordBot.getInstance()
.getConfig()
.getCouncilThread()
.keySet()
.stream()
.map(roleId -> DiscordBot.getGuild().getRoleById(roleId))
.collect(Collectors.toSet());
private static final Map<Role, List<Member>> membersByRole = new HashMap<>();
private static void initRolesAndMembers(Runnable loaded) {
List<Long> discordIds = SteamwarUser.getUsersWithDiscordId().stream()
.map(SteamwarUser::getDiscordId)
.collect(Collectors.toList());
membersByRole.clear();
AtomicInteger countdown = new AtomicInteger(0);
for (int i = 0; i < discordIds.size(); i += 100) {
countdown.incrementAndGet();
List<Long> retrieveIds = discordIds.subList(i, Math.min(discordIds.size(), i + 100));
DiscordBot.getGuild().retrieveMembersByIds(retrieveIds)
.onSuccess(members -> {
members.forEach(member -> {
for (Role role : roleSet) {
if (member.getUnsortedRoles().contains(role)) {
membersByRole.computeIfAbsent(role, __ -> new ArrayList<>()).add(member);
}
}
});
if (countdown.decrementAndGet() == 0) {
loaded.run();
}
});
}
}
public static void initCouncilChannels() {
initRolesAndMembers(() -> {
DiscordBot.getInstance()
.getConfig()
.getCouncilThread()
.forEach((roleId, threadId) -> {
new CouncilChannel(DiscordBot.getGuild().getRoleById(roleId), DiscordBot.getGuild().getThreadChannelById(threadId));
});
});
}
public static void updateAll() { public static void updateAll() {
channels.forEach(StaticMessageChannel::update); initRolesAndMembers(() -> {
channels.forEach(StaticMessageChannel::update);
});
} }
public CouncilChannel(Role role, ThreadChannel threadChannel) { public CouncilChannel(Role role, ThreadChannel threadChannel) {
super(threadChannel, (consumer) -> { super(threadChannel, () -> {
MessageCreateBuilder messageCreateBuilder = new MessageCreateBuilder(); MessageCreateBuilder messageCreateBuilder = new MessageCreateBuilder();
messageCreateBuilder.setContent("# Ratsmitglieder"); messageCreateBuilder.setContent("# Ratsmitglieder");
DiscordBot.getGuild().findMembersWithRoles(role).onError(throwable -> { membersByRole.get(role)
VelocityCore.getLogger().warning("Could not get members for " + role.getName()); .stream()
consumer.accept(messageCreateBuilder); .map(member -> {
}).onSuccess(members -> { SteamwarUser steamwarUser = SteamwarUser.get(member.getIdLong());
members.stream() String name = steamwarUser == null ? member.getEffectiveName() : steamwarUser.getUserName();
.map(member -> { UUID uuid = steamwarUser == null ? null : steamwarUser.getUUID();
SteamwarUser steamwarUser = SteamwarUser.get(member.getIdLong()); return Map.entry(name, uuid);
String name = steamwarUser == null ? member.getEffectiveName() : steamwarUser.getUserName(); })
UUID uuid = steamwarUser == null ? null : steamwarUser.getUUID(); .sorted(Map.Entry.comparingByKey())
return Map.entry(name, uuid); .forEach(entry -> {
}) messageCreateBuilder.addEmbeds(new EmbedBuilder()
.sorted(Comparator.comparing(Map.Entry::getKey)) .setTitle(entry.getKey())
.forEach(entry -> { .setImage(entry.getValue() == null ? null : "https://api.steamwar.de/data/skin/" + entry.getValue())
messageCreateBuilder.addEmbeds(new EmbedBuilder() .build());
.setTitle(entry.getKey()) });
.setImage(entry.getValue() == null ? null : "https://api.steamwar.de/data/skin/" + entry.getValue().toString()) return messageCreateBuilder;
.build());
});
consumer.accept(messageCreateBuilder);
});
}, event -> { }, event -> {
}); });
@@ -40,7 +40,7 @@ public class StaticMessageChannel extends DiscordChannel {
} }
private Message message; private Message message;
private final Consumer<Consumer<MessageCreateBuilder>> supplier; private final Supplier<MessageCreateBuilder> supplier;
private final Consumer<GenericComponentInteractionCreateEvent> interaction; private final Consumer<GenericComponentInteractionCreateEvent> interaction;
public StaticMessageChannel(String channel, Supplier<MessageCreateBuilder> supplier) { public StaticMessageChannel(String channel, Supplier<MessageCreateBuilder> supplier) {
@@ -50,12 +50,12 @@ public class StaticMessageChannel extends DiscordChannel {
public StaticMessageChannel(String channel, Supplier<MessageCreateBuilder> supplier, Consumer<GenericComponentInteractionCreateEvent> interaction) { public StaticMessageChannel(String channel, Supplier<MessageCreateBuilder> supplier, Consumer<GenericComponentInteractionCreateEvent> interaction) {
super(channel, 0); super(channel, 0);
this.supplier = messageCreateBuilderConsumer -> supplier.get(); this.supplier = supplier;
this.interaction = interaction; this.interaction = interaction;
init(); init();
} }
public StaticMessageChannel(MessageChannel channel, Consumer<Consumer<MessageCreateBuilder>> supplier, Consumer<GenericComponentInteractionCreateEvent> interaction) { public StaticMessageChannel(MessageChannel channel, Supplier<MessageCreateBuilder> supplier, Consumer<GenericComponentInteractionCreateEvent> interaction) {
super(channel, 0); super(channel, 0);
this.supplier = supplier; this.supplier = supplier;
this.interaction = interaction; this.interaction = interaction;
@@ -77,13 +77,11 @@ public class StaticMessageChannel extends DiscordChannel {
} }
public void update() { public void update() {
supplier.accept(messageCreateBuilder -> { if (message == null) {
if (message == null) { getChannel().sendMessage(supplier.get().build()).queue(m -> message = m);
getChannel().sendMessage(messageCreateBuilder.build()).queue(m -> message = m); } else {
} else { message.editMessage(MessageEditData.fromCreateData(supplier.get().build())).queue();
message.editMessage(MessageEditData.fromCreateData(messageCreateBuilder.build())).queue(); }
}
});
} }
@Override @Override