mirror of
https://github.com/DiscordSRV/Ascension.git
synced 2024-11-01 08:39:31 +01:00
Add support for sending to forums
This commit is contained in:
parent
f5b8829de1
commit
f0427d4890
@ -1,7 +1,12 @@
|
|||||||
package com.discordsrv.api.discord.entity.channel;
|
package com.discordsrv.api.discord.entity.channel;
|
||||||
|
|
||||||
import com.discordsrv.api.discord.entity.JDAEntity;
|
import com.discordsrv.api.discord.entity.JDAEntity;
|
||||||
|
import com.discordsrv.api.discord.entity.message.SendableDiscordMessage;
|
||||||
import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
|
import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public interface DiscordForumChannel extends DiscordChannel, DiscordThreadContainer, JDAEntity<ForumChannel> {
|
public interface DiscordForumChannel extends DiscordChannel, DiscordThreadContainer, JDAEntity<ForumChannel> {
|
||||||
|
|
||||||
|
CompletableFuture<DiscordThreadChannel> createPost(String name, SendableDiscordMessage message);
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,10 @@ public class ThreadConfig {
|
|||||||
|
|
||||||
@Comment("Specify the text or forum channel id and the name of the thread (the thread will be automatically created if it doesn't exist)")
|
@Comment("Specify the text or forum channel id and the name of the thread (the thread will be automatically created if it doesn't exist)")
|
||||||
public Long channelId = 0L;
|
public Long channelId = 0L;
|
||||||
|
|
||||||
public String threadName = "Minecraft Server chat bridge";
|
public String threadName = "Minecraft Server chat bridge";
|
||||||
|
|
||||||
|
@Comment("Does not effect forums")
|
||||||
public boolean privateThread = false;
|
public boolean privateThread = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ import com.discordsrv.api.discord.entity.guild.DiscordGuild;
|
|||||||
import com.discordsrv.api.discord.entity.guild.DiscordRole;
|
import com.discordsrv.api.discord.entity.guild.DiscordRole;
|
||||||
import com.discordsrv.api.discord.entity.interaction.command.CommandType;
|
import com.discordsrv.api.discord.entity.interaction.command.CommandType;
|
||||||
import com.discordsrv.api.discord.entity.interaction.command.DiscordCommand;
|
import com.discordsrv.api.discord.entity.interaction.command.DiscordCommand;
|
||||||
|
import com.discordsrv.api.discord.entity.message.SendableDiscordMessage;
|
||||||
import com.discordsrv.api.discord.exception.NotReadyException;
|
import com.discordsrv.api.discord.exception.NotReadyException;
|
||||||
import com.discordsrv.api.discord.exception.RestErrorResponseException;
|
import com.discordsrv.api.discord.exception.RestErrorResponseException;
|
||||||
import com.discordsrv.common.DiscordSRV;
|
import com.discordsrv.common.DiscordSRV;
|
||||||
@ -49,7 +50,9 @@ import com.github.benmanes.caffeine.cache.Expiry;
|
|||||||
import net.dv8tion.jda.api.JDA;
|
import net.dv8tion.jda.api.JDA;
|
||||||
import net.dv8tion.jda.api.entities.*;
|
import net.dv8tion.jda.api.entities.*;
|
||||||
import net.dv8tion.jda.api.entities.channel.Channel;
|
import net.dv8tion.jda.api.entities.channel.Channel;
|
||||||
|
import net.dv8tion.jda.api.entities.channel.attribute.IWebhookContainer;
|
||||||
import net.dv8tion.jda.api.entities.channel.concrete.*;
|
import net.dv8tion.jda.api.entities.channel.concrete.*;
|
||||||
|
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
|
||||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||||
import net.dv8tion.jda.api.entities.emoji.CustomEmoji;
|
import net.dv8tion.jda.api.entities.emoji.CustomEmoji;
|
||||||
import net.dv8tion.jda.api.exceptions.ErrorResponseException;
|
import net.dv8tion.jda.api.exceptions.ErrorResponseException;
|
||||||
@ -168,7 +171,7 @@ public class DiscordAPIImpl implements DiscordAPI {
|
|||||||
"Failed to deliver message to thread \""
|
"Failed to deliver message to thread \""
|
||||||
+ threadConfig.threadName + "\" in channel " + container
|
+ threadConfig.threadName + "\" in channel " + container
|
||||||
).accept(t);
|
).accept(t);
|
||||||
throw new RuntimeException(); // Just here to fail the future
|
throw new RuntimeException("Failed to deliver message to one or more threads");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (threadChannel != null) {
|
if (threadChannel != null) {
|
||||||
@ -248,7 +251,7 @@ public class DiscordAPIImpl implements DiscordAPI {
|
|||||||
private void unarchiveOrCreateThread(
|
private void unarchiveOrCreateThread(
|
||||||
ThreadConfig config,
|
ThreadConfig config,
|
||||||
DiscordThreadContainer container,
|
DiscordThreadContainer container,
|
||||||
DiscordThreadChannel thread,
|
@Nullable DiscordThreadChannel thread,
|
||||||
CompletableFuture<DiscordThreadChannel> future
|
CompletableFuture<DiscordThreadChannel> future
|
||||||
) {
|
) {
|
||||||
if (thread != null) {
|
if (thread != null) {
|
||||||
@ -268,7 +271,16 @@ public class DiscordAPIImpl implements DiscordAPI {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
container.createThread(config.threadName, config.privateThread).whenComplete(((threadChannel, t) -> {
|
CompletableFuture<DiscordThreadChannel> createFuture;
|
||||||
|
if (container instanceof DiscordForumChannel) {
|
||||||
|
createFuture = ((DiscordForumChannel) container).createPost(
|
||||||
|
config.threadName,
|
||||||
|
SendableDiscordMessage.builder().setContent("\u200B").build() // zero-width-space
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
createFuture = container.createThread(config.threadName, config.privateThread);
|
||||||
|
}
|
||||||
|
createFuture.whenComplete(((threadChannel, t) -> {
|
||||||
if (t != null) {
|
if (t != null) {
|
||||||
future.completeExceptionally(t);
|
future.completeExceptionally(t);
|
||||||
} else {
|
} else {
|
||||||
@ -538,12 +550,13 @@ public class DiscordAPIImpl implements DiscordAPI {
|
|||||||
return notReady();
|
return notReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
TextChannel textChannel = jda.getTextChannelById(channelId);
|
GuildChannel channel = jda.getGuildChannelById(channelId);
|
||||||
if (textChannel == null) {
|
IWebhookContainer webhookContainer = channel instanceof IWebhookContainer ? (IWebhookContainer) channel : null;
|
||||||
|
if (webhookContainer == null) {
|
||||||
return CompletableFutureUtil.failed(new IllegalArgumentException("Channel could not be found"));
|
return CompletableFutureUtil.failed(new IllegalArgumentException("Channel could not be found"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return textChannel.retrieveWebhooks().submit().thenApply(webhooks -> {
|
return webhookContainer.retrieveWebhooks().submit().thenApply(webhooks -> {
|
||||||
Webhook hook = null;
|
Webhook hook = null;
|
||||||
for (Webhook webhook : webhooks) {
|
for (Webhook webhook : webhooks) {
|
||||||
User user = webhook.getOwnerAsUser();
|
User user = webhook.getOwnerAsUser();
|
||||||
@ -563,7 +576,7 @@ public class DiscordAPIImpl implements DiscordAPI {
|
|||||||
return CompletableFuture.completedFuture(webhook);
|
return CompletableFuture.completedFuture(webhook);
|
||||||
}
|
}
|
||||||
|
|
||||||
return textChannel.createWebhook("DSRV").submit();
|
return webhookContainer.createWebhook("DSRV").submit();
|
||||||
}).thenApply(webhook ->
|
}).thenApply(webhook ->
|
||||||
WebhookClient.createClient(
|
WebhookClient.createClient(
|
||||||
webhook.getJDA(),
|
webhook.getJDA(),
|
||||||
|
@ -4,10 +4,14 @@ import com.discordsrv.api.discord.entity.channel.DiscordChannelType;
|
|||||||
import com.discordsrv.api.discord.entity.channel.DiscordForumChannel;
|
import com.discordsrv.api.discord.entity.channel.DiscordForumChannel;
|
||||||
import com.discordsrv.api.discord.entity.channel.DiscordThreadChannel;
|
import com.discordsrv.api.discord.entity.channel.DiscordThreadChannel;
|
||||||
import com.discordsrv.api.discord.entity.guild.DiscordGuild;
|
import com.discordsrv.api.discord.entity.guild.DiscordGuild;
|
||||||
|
import com.discordsrv.api.discord.entity.message.SendableDiscordMessage;
|
||||||
import com.discordsrv.common.DiscordSRV;
|
import com.discordsrv.common.DiscordSRV;
|
||||||
|
import com.discordsrv.common.discord.api.entity.message.util.SendableDiscordMessageUtil;
|
||||||
import net.dv8tion.jda.api.entities.channel.attribute.IThreadContainer;
|
import net.dv8tion.jda.api.entities.channel.attribute.IThreadContainer;
|
||||||
import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
|
import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
|
||||||
import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel;
|
import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel;
|
||||||
|
import net.dv8tion.jda.api.entities.channel.forums.ForumPost;
|
||||||
|
import net.dv8tion.jda.api.requests.restaction.AbstractThreadCreateAction;
|
||||||
import net.dv8tion.jda.api.requests.restaction.ThreadChannelAction;
|
import net.dv8tion.jda.api.requests.restaction.ThreadChannelAction;
|
||||||
import net.dv8tion.jda.api.requests.restaction.pagination.ThreadChannelPaginationAction;
|
import net.dv8tion.jda.api.requests.restaction.pagination.ThreadChannelPaginationAction;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -95,20 +99,31 @@ public class DiscordForumChannelImpl implements DiscordForumChannel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<DiscordThreadChannel> createThread(String name, boolean privateThread) {
|
public CompletableFuture<DiscordThreadChannel> createThread(String name, boolean privateThread) {
|
||||||
return thread(channel -> channel.createThreadChannel(name, privateThread));
|
throw new IllegalStateException("Cannot create Threads in Forums without a message");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<DiscordThreadChannel> createThread(String name, long messageId) {
|
public CompletableFuture<DiscordThreadChannel> createThread(String name, long messageId) {
|
||||||
return thread(channel -> channel.createThreadChannel(name, messageId));
|
return thread(channel -> channel.createThreadChannel(name, messageId), result -> result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<DiscordThreadChannel> createPost(String name, SendableDiscordMessage message) {
|
||||||
|
return thread(
|
||||||
|
channel -> channel.createForumPost(name, SendableDiscordMessageUtil.toJDASend(message)),
|
||||||
|
ForumPost::getThreadChannel
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("CodeBlock2Expr")
|
@SuppressWarnings("CodeBlock2Expr")
|
||||||
private CompletableFuture<DiscordThreadChannel> thread(Function<ForumChannel, ThreadChannelAction> action) {
|
private <R> CompletableFuture<DiscordThreadChannel> thread(
|
||||||
|
Function<ForumChannel, AbstractThreadCreateAction<R, ?>> action,
|
||||||
|
Function<R, ThreadChannel> resultMapper
|
||||||
|
) {
|
||||||
return discordSRV.discordAPI().mapExceptions(() -> {
|
return discordSRV.discordAPI().mapExceptions(() -> {
|
||||||
return action.apply(channel)
|
return action.apply(channel)
|
||||||
.submit()
|
.submit()
|
||||||
.thenApply(channel -> discordSRV.discordAPI().getThreadChannel(channel));
|
.thenApply(result -> discordSRV.discordAPI().getThreadChannel(resultMapper.apply(result)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ public class FullBootExtension implements BeforeAllCallback, ExtensionContext.St
|
|||||||
|
|
||||||
public static String BOT_TOKEN = System.getenv("DISCORDSRV_AUTOTEST_BOT_TOKEN");
|
public static String BOT_TOKEN = System.getenv("DISCORDSRV_AUTOTEST_BOT_TOKEN");
|
||||||
public static String TEST_CHANNEL_ID = System.getenv("DISCORDSRV_AUTOTEST_CHANNEL_ID");
|
public static String TEST_CHANNEL_ID = System.getenv("DISCORDSRV_AUTOTEST_CHANNEL_ID");
|
||||||
|
public static String FORUM_CHANNEL_ID = System.getenv("DISCORDSRV_AUTOTEST_FORUM_ID");
|
||||||
|
|
||||||
public boolean started = false;
|
public boolean started = false;
|
||||||
|
|
||||||
@ -16,6 +17,7 @@ public class FullBootExtension implements BeforeAllCallback, ExtensionContext.St
|
|||||||
public void beforeAll(ExtensionContext context) {
|
public void beforeAll(ExtensionContext context) {
|
||||||
Assumptions.assumeTrue(BOT_TOKEN != null, "Automated testing bot token");
|
Assumptions.assumeTrue(BOT_TOKEN != null, "Automated testing bot token");
|
||||||
Assumptions.assumeTrue(TEST_CHANNEL_ID != null, "Automated testing channel id");
|
Assumptions.assumeTrue(TEST_CHANNEL_ID != null, "Automated testing channel id");
|
||||||
|
Assumptions.assumeTrue(FORUM_CHANNEL_ID != null, "Automated testing forum id");
|
||||||
|
|
||||||
if (started) return;
|
if (started) return;
|
||||||
started = true;
|
started = true;
|
||||||
|
@ -215,6 +215,7 @@ public class MockDiscordSRV extends AbstractDiscordSRV<IBootstrap, MainConfig, C
|
|||||||
DestinationConfig destination = global.destination = new DestinationConfig();
|
DestinationConfig destination = global.destination = new DestinationConfig();
|
||||||
|
|
||||||
long channelId = Long.parseLong(FullBootExtension.TEST_CHANNEL_ID);
|
long channelId = Long.parseLong(FullBootExtension.TEST_CHANNEL_ID);
|
||||||
|
long forumId = Long.parseLong(FullBootExtension.FORUM_CHANNEL_ID);
|
||||||
|
|
||||||
List<Long> channelIds = destination.channelIds;
|
List<Long> channelIds = destination.channelIds;
|
||||||
channelIds.clear();
|
channelIds.clear();
|
||||||
@ -222,9 +223,14 @@ public class MockDiscordSRV extends AbstractDiscordSRV<IBootstrap, MainConfig, C
|
|||||||
|
|
||||||
List<ThreadConfig> threadConfigs = destination.threads;
|
List<ThreadConfig> threadConfigs = destination.threads;
|
||||||
threadConfigs.clear();
|
threadConfigs.clear();
|
||||||
|
|
||||||
ThreadConfig thread = new ThreadConfig();
|
ThreadConfig thread = new ThreadConfig();
|
||||||
thread.channelId = channelId;
|
thread.channelId = channelId;
|
||||||
threadConfigs.add(thread);
|
threadConfigs.add(thread);
|
||||||
|
|
||||||
|
ThreadConfig forumThread = new ThreadConfig();
|
||||||
|
thread.channelId = forumId;
|
||||||
|
threadConfigs.add(forumThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
@ -239,7 +245,7 @@ public class MockDiscordSRV extends AbstractDiscordSRV<IBootstrap, MainConfig, C
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() throws ConfigException {
|
public void load() {
|
||||||
messagesConfigLoaded = true;
|
messagesConfigLoaded = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -146,7 +146,7 @@ public class MinecraftToDiscordChatMessageTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
success.complete(text == 1 && thread == 1);
|
success.complete(text == 1 && thread == 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user