mirror of
https://github.com/DiscordSRV/Ascension.git
synced 2024-11-01 08:39:31 +01:00
Add support for webhooks in threads, add username format option for mirroring
This commit is contained in:
parent
88ef85c65e
commit
0a128e37e9
@ -24,24 +24,8 @@
|
|||||||
package com.discordsrv.api.discord.api.entity.channel;
|
package com.discordsrv.api.discord.api.entity.channel;
|
||||||
|
|
||||||
import com.discordsrv.api.discord.api.entity.Mentionable;
|
import com.discordsrv.api.discord.api.entity.Mentionable;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A regular Discord channel that messages can be sent to (threads not included).
|
* A regular Discord channel that messages can be sent to.
|
||||||
*/
|
*/
|
||||||
public interface DiscordGuildMessageChannel extends DiscordMessageChannel, DiscordGuildChannel, Mentionable {
|
public interface DiscordGuildMessageChannel extends DiscordMessageChannel, DiscordGuildChannel, Mentionable {}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
List<DiscordThreadChannel> getActiveThreads();
|
|
||||||
|
|
||||||
CompletableFuture<List<DiscordThreadChannel>> retrieveArchivedPrivateThreads();
|
|
||||||
CompletableFuture<List<DiscordThreadChannel>> retrieveArchivedJoinedPrivateThreads();
|
|
||||||
CompletableFuture<List<DiscordThreadChannel>> retrieveArchivedPublicThreads();
|
|
||||||
|
|
||||||
CompletableFuture<DiscordThreadChannel> createThread(String name, boolean privateThread);
|
|
||||||
CompletableFuture<DiscordThreadChannel> createThread(String name, long messageId);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -26,7 +26,7 @@ package com.discordsrv.api.discord.api.entity.channel;
|
|||||||
import com.discordsrv.api.DiscordSRVApi;
|
import com.discordsrv.api.DiscordSRVApi;
|
||||||
import net.dv8tion.jda.api.entities.NewsChannel;
|
import net.dv8tion.jda.api.entities.NewsChannel;
|
||||||
|
|
||||||
public interface DiscordNewsChannel extends DiscordGuildMessageChannel {
|
public interface DiscordNewsChannel extends DiscordGuildMessageChannel, DiscordThreadContainer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the JDA representation of this object. This should not be used if it can be avoided.
|
* Returns the JDA representation of this object. This should not be used if it can be avoided.
|
||||||
|
@ -30,7 +30,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
/**
|
/**
|
||||||
* A Discord text channel.
|
* A Discord text channel.
|
||||||
*/
|
*/
|
||||||
public interface DiscordTextChannel extends DiscordGuildMessageChannel {
|
public interface DiscordTextChannel extends DiscordGuildMessageChannel, DiscordThreadContainer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the topic of the text channel.
|
* Gets the topic of the text channel.
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the DiscordSRV API, licensed under the MIT License
|
||||||
|
* Copyright (c) 2016-2022 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.discordsrv.api.discord.api.entity.channel;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Discord channel that contains threads.
|
||||||
|
*/
|
||||||
|
public interface DiscordThreadContainer extends DiscordGuildChannel {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
List<DiscordThreadChannel> getActiveThreads();
|
||||||
|
|
||||||
|
CompletableFuture<List<DiscordThreadChannel>> retrieveArchivedPrivateThreads();
|
||||||
|
CompletableFuture<List<DiscordThreadChannel>> retrieveArchivedJoinedPrivateThreads();
|
||||||
|
CompletableFuture<List<DiscordThreadChannel>> retrieveArchivedPublicThreads();
|
||||||
|
|
||||||
|
CompletableFuture<DiscordThreadChannel> createThread(String name, boolean privateThread);
|
||||||
|
CompletableFuture<DiscordThreadChannel> createThread(String name, long messageId);
|
||||||
|
}
|
@ -27,7 +27,7 @@ dependencies {
|
|||||||
api 'dev.vankka.dependencydownload:runtime:' + rootProject.ddVersion
|
api 'dev.vankka.dependencydownload:runtime:' + rootProject.ddVersion
|
||||||
|
|
||||||
// Discord Webhooks
|
// Discord Webhooks
|
||||||
runtimeDownloadApi 'club.minnced:discord-webhooks:0.5.7'
|
runtimeDownloadApi 'club.minnced:discord-webhooks:0.7.5'
|
||||||
|
|
||||||
// Apache Commons
|
// Apache Commons
|
||||||
runtimeDownloadApi 'org.apache.commons:commons-lang3:3.12.0'
|
runtimeDownloadApi 'org.apache.commons:commons-lang3:3.12.0'
|
||||||
|
@ -29,4 +29,9 @@ public class MirroringConfig {
|
|||||||
|
|
||||||
@Comment("Users, bots and webhooks to ignore when mirroring")
|
@Comment("Users, bots and webhooks to ignore when mirroring")
|
||||||
public DiscordIgnores ignores = new DiscordIgnores();
|
public DiscordIgnores ignores = new DiscordIgnores();
|
||||||
|
|
||||||
|
@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 being grouped together")
|
||||||
|
public String usernameFormat = "%user_effective_name% [M]";
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ import com.discordsrv.api.discord.events.message.DiscordMessageReceiveEvent;
|
|||||||
import com.discordsrv.api.discord.events.message.DiscordMessageUpdateEvent;
|
import com.discordsrv.api.discord.events.message.DiscordMessageUpdateEvent;
|
||||||
import com.discordsrv.api.event.bus.Subscribe;
|
import com.discordsrv.api.event.bus.Subscribe;
|
||||||
import com.discordsrv.common.DiscordSRV;
|
import com.discordsrv.common.DiscordSRV;
|
||||||
import com.discordsrv.common.discord.api.entity.channel.DiscordMessageChannelImpl;
|
import com.discordsrv.common.discord.api.entity.channel.AbstractDiscordMessageChannel;
|
||||||
import com.discordsrv.common.discord.api.entity.guild.DiscordGuildMemberImpl;
|
import com.discordsrv.common.discord.api.entity.guild.DiscordGuildMemberImpl;
|
||||||
import com.discordsrv.common.discord.api.entity.guild.DiscordRoleImpl;
|
import com.discordsrv.common.discord.api.entity.guild.DiscordRoleImpl;
|
||||||
import com.discordsrv.common.discord.api.entity.message.ReceivedDiscordMessageImpl;
|
import com.discordsrv.common.discord.api.entity.message.ReceivedDiscordMessageImpl;
|
||||||
@ -47,7 +47,7 @@ public class DiscordAPIEventModule extends AbstractModule<DiscordSRV> {
|
|||||||
@Subscribe
|
@Subscribe
|
||||||
public void onMessageReceived(MessageReceivedEvent event) {
|
public void onMessageReceived(MessageReceivedEvent event) {
|
||||||
discordSRV.eventBus().publish(new DiscordMessageReceiveEvent(
|
discordSRV.eventBus().publish(new DiscordMessageReceiveEvent(
|
||||||
DiscordMessageChannelImpl.get(discordSRV, event.getChannel()),
|
AbstractDiscordMessageChannel.get(discordSRV, event.getChannel()),
|
||||||
ReceivedDiscordMessageImpl.fromJDA(discordSRV, event.getMessage())
|
ReceivedDiscordMessageImpl.fromJDA(discordSRV, event.getMessage())
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -55,7 +55,7 @@ public class DiscordAPIEventModule extends AbstractModule<DiscordSRV> {
|
|||||||
@Subscribe
|
@Subscribe
|
||||||
public void onMessageUpdate(MessageUpdateEvent event) {
|
public void onMessageUpdate(MessageUpdateEvent event) {
|
||||||
discordSRV.eventBus().publish(new DiscordMessageUpdateEvent(
|
discordSRV.eventBus().publish(new DiscordMessageUpdateEvent(
|
||||||
DiscordMessageChannelImpl.get(discordSRV, event.getChannel()),
|
AbstractDiscordMessageChannel.get(discordSRV, event.getChannel()),
|
||||||
ReceivedDiscordMessageImpl.fromJDA(discordSRV, event.getMessage())
|
ReceivedDiscordMessageImpl.fromJDA(discordSRV, event.getMessage())
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ public class DiscordAPIEventModule extends AbstractModule<DiscordSRV> {
|
|||||||
@Subscribe
|
@Subscribe
|
||||||
public void onMessageDelete(MessageDeleteEvent event) {
|
public void onMessageDelete(MessageDeleteEvent event) {
|
||||||
discordSRV.eventBus().publish(new DiscordMessageDeleteEvent(
|
discordSRV.eventBus().publish(new DiscordMessageDeleteEvent(
|
||||||
DiscordMessageChannelImpl.get(discordSRV, event.getChannel()),
|
AbstractDiscordMessageChannel.get(discordSRV, event.getChannel()),
|
||||||
event.getMessageIdLong()
|
event.getMessageIdLong()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@ import club.minnced.discord.webhook.WebhookClient;
|
|||||||
import club.minnced.discord.webhook.receive.ReadonlyMessage;
|
import club.minnced.discord.webhook.receive.ReadonlyMessage;
|
||||||
import club.minnced.discord.webhook.send.WebhookMessage;
|
import club.minnced.discord.webhook.send.WebhookMessage;
|
||||||
import com.discordsrv.api.discord.api.entity.channel.DiscordGuildMessageChannel;
|
import com.discordsrv.api.discord.api.entity.channel.DiscordGuildMessageChannel;
|
||||||
import com.discordsrv.api.discord.api.entity.channel.DiscordThreadChannel;
|
|
||||||
import com.discordsrv.api.discord.api.entity.guild.DiscordGuild;
|
import com.discordsrv.api.discord.api.entity.guild.DiscordGuild;
|
||||||
import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessage;
|
import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessage;
|
||||||
import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage;
|
import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage;
|
||||||
@ -30,30 +29,30 @@ import com.discordsrv.common.DiscordSRV;
|
|||||||
import com.discordsrv.common.discord.api.entity.guild.DiscordGuildImpl;
|
import com.discordsrv.common.discord.api.entity.guild.DiscordGuildImpl;
|
||||||
import com.discordsrv.common.discord.api.entity.message.ReceivedDiscordMessageImpl;
|
import com.discordsrv.common.discord.api.entity.message.ReceivedDiscordMessageImpl;
|
||||||
import com.discordsrv.common.discord.api.entity.message.util.SendableDiscordMessageUtil;
|
import com.discordsrv.common.discord.api.entity.message.util.SendableDiscordMessageUtil;
|
||||||
import net.dv8tion.jda.api.entities.*;
|
import net.dv8tion.jda.api.entities.GuildMessageChannel;
|
||||||
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
|
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||||
import net.dv8tion.jda.api.requests.restaction.MessageAction;
|
import net.dv8tion.jda.api.requests.restaction.MessageAction;
|
||||||
import net.dv8tion.jda.api.requests.restaction.ThreadChannelAction;
|
|
||||||
import net.dv8tion.jda.api.requests.restaction.pagination.ThreadChannelPaginationAction;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public abstract class DiscordGuildMessageChannelImpl<T extends GuildMessageChannel & IThreadContainer>
|
public abstract class AbstractDiscordGuildMessageChannel<T extends GuildMessageChannel>
|
||||||
extends DiscordMessageChannelImpl<T>
|
extends AbstractDiscordMessageChannel<T>
|
||||||
implements DiscordGuildMessageChannel {
|
implements DiscordGuildMessageChannel {
|
||||||
|
|
||||||
private final DiscordGuild guild;
|
private final DiscordGuild guild;
|
||||||
|
|
||||||
public DiscordGuildMessageChannelImpl(DiscordSRV discordSRV, T channel) {
|
public AbstractDiscordGuildMessageChannel(DiscordSRV discordSRV, T channel) {
|
||||||
super(discordSRV, channel);
|
super(discordSRV, channel);
|
||||||
this.guild = new DiscordGuildImpl(discordSRV, channel.getGuild());
|
this.guild = new DiscordGuildImpl(discordSRV, channel.getGuild());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CompletableFuture<WebhookClient> queryWebhookClient() {
|
||||||
|
return discordSRV.discordAPI().queryWebhookClient(getId());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull String getName() {
|
public @NotNull String getName() {
|
||||||
return channel.getName();
|
return channel.getName();
|
||||||
@ -69,60 +68,6 @@ public abstract class DiscordGuildMessageChannelImpl<T extends GuildMessageChann
|
|||||||
return guild;
|
return guild;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull List<DiscordThreadChannel> getActiveThreads() {
|
|
||||||
List<ThreadChannel> threads = channel.getThreadChannels();
|
|
||||||
List<DiscordThreadChannel> threadChannels = new ArrayList<>(threads.size());
|
|
||||||
for (ThreadChannel thread : threads) {
|
|
||||||
threadChannels.add(new DiscordThreadChannelImpl(discordSRV, thread));
|
|
||||||
}
|
|
||||||
return threadChannels;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<List<DiscordThreadChannel>> retrieveArchivedPrivateThreads() {
|
|
||||||
return threads(IThreadContainer::retrieveArchivedPrivateThreadChannels);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<List<DiscordThreadChannel>> retrieveArchivedJoinedPrivateThreads() {
|
|
||||||
return threads(IThreadContainer::retrieveArchivedPrivateJoinedThreadChannels);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<List<DiscordThreadChannel>> retrieveArchivedPublicThreads() {
|
|
||||||
return threads(IThreadContainer::retrieveArchivedPublicThreadChannels);
|
|
||||||
}
|
|
||||||
|
|
||||||
private CompletableFuture<List<DiscordThreadChannel>> threads(Function<IThreadContainer, ThreadChannelPaginationAction> action) {
|
|
||||||
return discordSRV.discordAPI().mapExceptions(() ->
|
|
||||||
action.apply(channel)
|
|
||||||
.submit()
|
|
||||||
.thenApply(channels -> channels.stream()
|
|
||||||
.map(channel -> new DiscordThreadChannelImpl(discordSRV, channel))
|
|
||||||
.collect(Collectors.toList())
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<DiscordThreadChannel> createThread(String name, boolean privateThread) {
|
|
||||||
return thread(channel -> channel.createThreadChannel(name, privateThread));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<DiscordThreadChannel> createThread(String name, long messageId) {
|
|
||||||
return thread(channel -> channel.createThreadChannel(name, messageId));
|
|
||||||
}
|
|
||||||
|
|
||||||
private CompletableFuture<DiscordThreadChannel> thread(Function<T, ThreadChannelAction> action) {
|
|
||||||
return discordSRV.discordAPI().mapExceptions(() ->
|
|
||||||
action.apply(channel)
|
|
||||||
.submit()
|
|
||||||
.thenApply(channel -> new DiscordThreadChannelImpl(discordSRV, channel))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull CompletableFuture<ReceivedDiscordMessage> sendMessage(@NotNull SendableDiscordMessage message) {
|
public @NotNull CompletableFuture<ReceivedDiscordMessage> sendMessage(@NotNull SendableDiscordMessage message) {
|
||||||
return message(message, WebhookClient::send, MessageChannel::sendMessage);
|
return message(message, WebhookClient::send, MessageChannel::sendMessage);
|
||||||
@ -144,7 +89,7 @@ public abstract class DiscordGuildMessageChannelImpl<T extends GuildMessageChann
|
|||||||
return discordSRV.discordAPI().mapExceptions(() -> {
|
return discordSRV.discordAPI().mapExceptions(() -> {
|
||||||
CompletableFuture<ReceivedDiscordMessage> future;
|
CompletableFuture<ReceivedDiscordMessage> future;
|
||||||
if (message.isWebhookMessage()) {
|
if (message.isWebhookMessage()) {
|
||||||
future = discordSRV.discordAPI().queryWebhookClient(getId())
|
future = queryWebhookClient()
|
||||||
.thenCompose(client -> webhookFunction.apply(
|
.thenCompose(client -> webhookFunction.apply(
|
||||||
client, SendableDiscordMessageUtil.toWebhook(message)))
|
client, SendableDiscordMessageUtil.toWebhook(message)))
|
||||||
.thenApply(msg -> ReceivedDiscordMessageImpl.fromWebhook(discordSRV, msg));
|
.thenApply(msg -> ReceivedDiscordMessageImpl.fromWebhook(discordSRV, msg));
|
@ -24,10 +24,10 @@ import net.dv8tion.jda.api.entities.*;
|
|||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public abstract class DiscordMessageChannelImpl<T extends MessageChannel>
|
public abstract class AbstractDiscordMessageChannel<T extends MessageChannel>
|
||||||
implements DiscordMessageChannel {
|
implements DiscordMessageChannel {
|
||||||
|
|
||||||
public static DiscordMessageChannelImpl<?> get(DiscordSRV discordSRV, MessageChannel messageChannel) {
|
public static AbstractDiscordMessageChannel<?> get(DiscordSRV discordSRV, MessageChannel messageChannel) {
|
||||||
if (messageChannel instanceof TextChannel) {
|
if (messageChannel instanceof TextChannel) {
|
||||||
return new DiscordTextChannelImpl(discordSRV, (TextChannel) messageChannel);
|
return new DiscordTextChannelImpl(discordSRV, (TextChannel) messageChannel);
|
||||||
} else if (messageChannel instanceof ThreadChannel) {
|
} else if (messageChannel instanceof ThreadChannel) {
|
||||||
@ -44,7 +44,7 @@ public abstract class DiscordMessageChannelImpl<T extends MessageChannel>
|
|||||||
protected final DiscordSRV discordSRV;
|
protected final DiscordSRV discordSRV;
|
||||||
protected final T channel;
|
protected final T channel;
|
||||||
|
|
||||||
public DiscordMessageChannelImpl(DiscordSRV discordSRV, T channel) {
|
public AbstractDiscordMessageChannel(DiscordSRV discordSRV, T channel) {
|
||||||
this.discordSRV = discordSRV;
|
this.discordSRV = discordSRV;
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ public abstract class DiscordMessageChannelImpl<T extends MessageChannel>
|
|||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
DiscordGuildMessageChannelImpl<?> that = (DiscordGuildMessageChannelImpl<?>) o;
|
AbstractDiscordGuildMessageChannel<?> that = (AbstractDiscordGuildMessageChannel<?>) o;
|
||||||
return Objects.equals(getId(), that.getId());
|
return Objects.equals(getId(), that.getId());
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||||
|
* Copyright (c) 2016-2022 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.discordsrv.common.discord.api.entity.channel;
|
||||||
|
|
||||||
|
import com.discordsrv.api.discord.api.entity.channel.DiscordGuildMessageChannel;
|
||||||
|
import com.discordsrv.api.discord.api.entity.channel.DiscordThreadChannel;
|
||||||
|
import com.discordsrv.api.discord.api.entity.channel.DiscordThreadContainer;
|
||||||
|
import com.discordsrv.common.DiscordSRV;
|
||||||
|
import net.dv8tion.jda.api.entities.GuildMessageChannel;
|
||||||
|
import net.dv8tion.jda.api.entities.IThreadContainer;
|
||||||
|
import net.dv8tion.jda.api.entities.ThreadChannel;
|
||||||
|
import net.dv8tion.jda.api.requests.restaction.ThreadChannelAction;
|
||||||
|
import net.dv8tion.jda.api.requests.restaction.pagination.ThreadChannelPaginationAction;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class AbstractDiscordThreadedGuildMessageChannel<T extends GuildMessageChannel & IThreadContainer>
|
||||||
|
extends AbstractDiscordGuildMessageChannel<T>
|
||||||
|
implements DiscordGuildMessageChannel, DiscordThreadContainer {
|
||||||
|
|
||||||
|
public AbstractDiscordThreadedGuildMessageChannel(DiscordSRV discordSRV, T channel) {
|
||||||
|
super(discordSRV, channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull List<DiscordThreadChannel> getActiveThreads() {
|
||||||
|
List<ThreadChannel> threads = channel.getThreadChannels();
|
||||||
|
List<DiscordThreadChannel> threadChannels = new ArrayList<>(threads.size());
|
||||||
|
for (ThreadChannel thread : threads) {
|
||||||
|
threadChannels.add(new DiscordThreadChannelImpl(discordSRV, thread));
|
||||||
|
}
|
||||||
|
return threadChannels;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<List<DiscordThreadChannel>> retrieveArchivedPrivateThreads() {
|
||||||
|
return threads(IThreadContainer::retrieveArchivedPrivateThreadChannels);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<List<DiscordThreadChannel>> retrieveArchivedJoinedPrivateThreads() {
|
||||||
|
return threads(IThreadContainer::retrieveArchivedPrivateJoinedThreadChannels);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<List<DiscordThreadChannel>> retrieveArchivedPublicThreads() {
|
||||||
|
return threads(IThreadContainer::retrieveArchivedPublicThreadChannels);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CompletableFuture<List<DiscordThreadChannel>> threads(
|
||||||
|
Function<IThreadContainer, ThreadChannelPaginationAction> action) {
|
||||||
|
return discordSRV.discordAPI().mapExceptions(() ->
|
||||||
|
action.apply(channel)
|
||||||
|
.submit()
|
||||||
|
.thenApply(channels -> channels.stream()
|
||||||
|
.map(channel -> new DiscordThreadChannelImpl(discordSRV, channel))
|
||||||
|
.collect(Collectors.toList())
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<DiscordThreadChannel> createThread(String name, boolean privateThread) {
|
||||||
|
return thread(channel -> channel.createThreadChannel(name, privateThread));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<DiscordThreadChannel> createThread(String name, long messageId) {
|
||||||
|
return thread(channel -> channel.createThreadChannel(name, messageId));
|
||||||
|
}
|
||||||
|
|
||||||
|
private CompletableFuture<DiscordThreadChannel> thread(Function<T, ThreadChannelAction> action) {
|
||||||
|
return discordSRV.discordAPI().mapExceptions(() ->
|
||||||
|
action.apply(channel)
|
||||||
|
.submit()
|
||||||
|
.thenApply(channel -> new DiscordThreadChannelImpl(discordSRV, channel))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -32,7 +32,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public class DiscordDMChannelImpl extends DiscordMessageChannelImpl<PrivateChannel> implements DiscordDMChannel {
|
public class DiscordDMChannelImpl extends AbstractDiscordMessageChannel<PrivateChannel> implements DiscordDMChannel {
|
||||||
|
|
||||||
private final DiscordUser user;
|
private final DiscordUser user;
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ import com.discordsrv.common.DiscordSRV;
|
|||||||
import net.dv8tion.jda.api.entities.NewsChannel;
|
import net.dv8tion.jda.api.entities.NewsChannel;
|
||||||
|
|
||||||
public class DiscordNewsChannelImpl
|
public class DiscordNewsChannelImpl
|
||||||
extends DiscordGuildMessageChannelImpl<NewsChannel>
|
extends AbstractDiscordThreadedGuildMessageChannel<NewsChannel>
|
||||||
implements DiscordNewsChannel {
|
implements DiscordNewsChannel {
|
||||||
|
|
||||||
public DiscordNewsChannelImpl(DiscordSRV discordSRV, NewsChannel channel) {
|
public DiscordNewsChannelImpl(DiscordSRV discordSRV, NewsChannel channel) {
|
||||||
|
@ -23,7 +23,8 @@ import com.discordsrv.common.DiscordSRV;
|
|||||||
import net.dv8tion.jda.api.entities.TextChannel;
|
import net.dv8tion.jda.api.entities.TextChannel;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public class DiscordTextChannelImpl extends DiscordGuildMessageChannelImpl<TextChannel> implements DiscordTextChannel {
|
public class DiscordTextChannelImpl extends AbstractDiscordThreadedGuildMessageChannel<TextChannel>
|
||||||
|
implements DiscordTextChannel {
|
||||||
|
|
||||||
public DiscordTextChannelImpl(DiscordSRV discordSRV, TextChannel textChannel) {
|
public DiscordTextChannelImpl(DiscordSRV discordSRV, TextChannel textChannel) {
|
||||||
super(discordSRV, textChannel);
|
super(discordSRV, textChannel);
|
||||||
|
@ -18,15 +18,12 @@
|
|||||||
|
|
||||||
package com.discordsrv.common.discord.api.entity.channel;
|
package com.discordsrv.common.discord.api.entity.channel;
|
||||||
|
|
||||||
|
import club.minnced.discord.webhook.WebhookClient;
|
||||||
import com.discordsrv.api.discord.api.entity.channel.DiscordTextChannel;
|
import com.discordsrv.api.discord.api.entity.channel.DiscordTextChannel;
|
||||||
import com.discordsrv.api.discord.api.entity.channel.DiscordThreadChannel;
|
import com.discordsrv.api.discord.api.entity.channel.DiscordThreadChannel;
|
||||||
import com.discordsrv.api.discord.api.entity.guild.DiscordGuild;
|
import com.discordsrv.api.discord.api.entity.guild.DiscordGuild;
|
||||||
import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessage;
|
|
||||||
import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage;
|
|
||||||
import com.discordsrv.common.DiscordSRV;
|
import com.discordsrv.common.DiscordSRV;
|
||||||
import com.discordsrv.common.discord.api.entity.guild.DiscordGuildImpl;
|
import com.discordsrv.common.discord.api.entity.guild.DiscordGuildImpl;
|
||||||
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.IThreadContainer;
|
import net.dv8tion.jda.api.entities.IThreadContainer;
|
||||||
import net.dv8tion.jda.api.entities.TextChannel;
|
import net.dv8tion.jda.api.entities.TextChannel;
|
||||||
import net.dv8tion.jda.api.entities.ThreadChannel;
|
import net.dv8tion.jda.api.entities.ThreadChannel;
|
||||||
@ -34,7 +31,8 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public class DiscordThreadChannelImpl extends DiscordMessageChannelImpl<ThreadChannel> implements DiscordThreadChannel {
|
public class DiscordThreadChannelImpl extends AbstractDiscordGuildMessageChannel<ThreadChannel>
|
||||||
|
implements DiscordThreadChannel {
|
||||||
|
|
||||||
private final DiscordTextChannel textChannel;
|
private final DiscordTextChannel textChannel;
|
||||||
private final DiscordGuild guild;
|
private final DiscordGuild guild;
|
||||||
@ -50,40 +48,10 @@ public class DiscordThreadChannelImpl extends DiscordMessageChannelImpl<ThreadCh
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull CompletableFuture<ReceivedDiscordMessage> sendMessage(@NotNull SendableDiscordMessage message) {
|
public CompletableFuture<WebhookClient> queryWebhookClient() {
|
||||||
if (message.isWebhookMessage()) {
|
return discordSRV.discordAPI()
|
||||||
throw new IllegalArgumentException("Cannot send webhook messages to ThreadChannels");
|
.queryWebhookClient(getParentChannel().getId())
|
||||||
}
|
.thenApply(client -> client.onThread(getId()));
|
||||||
|
|
||||||
return discordSRV.discordAPI().mapExceptions(
|
|
||||||
channel.sendMessage(SendableDiscordMessageUtil.toJDA(message))
|
|
||||||
.submit()
|
|
||||||
.thenApply(msg -> ReceivedDiscordMessageImpl.fromJDA(discordSRV, msg))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<Void> deleteMessageById(long id, boolean webhookMessage) {
|
|
||||||
if (webhookMessage) {
|
|
||||||
throw new IllegalArgumentException("ThreadChannels do not contain webhook messages");
|
|
||||||
}
|
|
||||||
|
|
||||||
return discordSRV.discordAPI().mapExceptions(
|
|
||||||
channel.deleteMessageById(id).submit()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull CompletableFuture<ReceivedDiscordMessage> editMessageById(long id, @NotNull SendableDiscordMessage message) {
|
|
||||||
if (message.isWebhookMessage()) {
|
|
||||||
throw new IllegalArgumentException("Cannot send webhook messages to ThreadChannels");
|
|
||||||
}
|
|
||||||
|
|
||||||
return discordSRV.discordAPI().mapExceptions(
|
|
||||||
channel.editMessageById(id, SendableDiscordMessageUtil.toJDA(message))
|
|
||||||
.submit()
|
|
||||||
.thenApply(msg -> ReceivedDiscordMessageImpl.fromJDA(discordSRV, msg))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -41,7 +41,7 @@ import com.discordsrv.common.DiscordSRV;
|
|||||||
import com.discordsrv.common.component.util.ComponentUtil;
|
import com.discordsrv.common.component.util.ComponentUtil;
|
||||||
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
|
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
|
||||||
import com.discordsrv.common.discord.api.entity.DiscordUserImpl;
|
import com.discordsrv.common.discord.api.entity.DiscordUserImpl;
|
||||||
import com.discordsrv.common.discord.api.entity.channel.DiscordMessageChannelImpl;
|
import com.discordsrv.common.discord.api.entity.channel.AbstractDiscordMessageChannel;
|
||||||
import com.discordsrv.common.discord.api.entity.guild.DiscordGuildMemberImpl;
|
import com.discordsrv.common.discord.api.entity.guild.DiscordGuildMemberImpl;
|
||||||
import com.discordsrv.common.function.OrDefault;
|
import com.discordsrv.common.function.OrDefault;
|
||||||
import com.discordsrv.common.future.util.CompletableFutureUtil;
|
import com.discordsrv.common.future.util.CompletableFutureUtil;
|
||||||
@ -71,7 +71,7 @@ public class ReceivedDiscordMessageImpl extends SendableDiscordMessageImpl imple
|
|||||||
String webhookUsername = webhookMessage ? message.getAuthor().getName() : null;
|
String webhookUsername = webhookMessage ? message.getAuthor().getName() : null;
|
||||||
String webhookAvatarUrl = webhookMessage ? message.getAuthor().getEffectiveAvatarUrl() : null;
|
String webhookAvatarUrl = webhookMessage ? message.getAuthor().getEffectiveAvatarUrl() : null;
|
||||||
|
|
||||||
DiscordMessageChannel channel = DiscordMessageChannelImpl.get(discordSRV, message.getChannel());
|
DiscordMessageChannel channel = AbstractDiscordMessageChannel.get(discordSRV, message.getChannel());
|
||||||
DiscordUser user = new DiscordUserImpl(discordSRV, message.getAuthor());
|
DiscordUser user = new DiscordUserImpl(discordSRV, message.getAuthor());
|
||||||
|
|
||||||
Member member = message.getMember();
|
Member member = message.getMember();
|
||||||
|
@ -41,6 +41,7 @@ import com.discordsrv.common.future.util.CompletableFutureUtil;
|
|||||||
import com.discordsrv.common.logging.NamedLogger;
|
import com.discordsrv.common.logging.NamedLogger;
|
||||||
import com.discordsrv.common.module.type.AbstractModule;
|
import com.discordsrv.common.module.type.AbstractModule;
|
||||||
import com.github.benmanes.caffeine.cache.Cache;
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
@ -72,7 +73,7 @@ public class DiscordMessageMirroringModule extends AbstractModule<DiscordSRV> {
|
|||||||
ReceivedDiscordMessage message = event.getDiscordMessage();
|
ReceivedDiscordMessage message = event.getDiscordMessage();
|
||||||
DiscordMessageChannel channel = event.getChannel();
|
DiscordMessageChannel channel = event.getChannel();
|
||||||
|
|
||||||
List<DiscordMessageChannel> mirrorChannels = new ArrayList<>();
|
List<Pair<DiscordMessageChannel, OrDefault<MirroringConfig>>> mirrorChannels = new ArrayList<>();
|
||||||
List<CompletableFuture<DiscordThreadChannel>> futures = new ArrayList<>();
|
List<CompletableFuture<DiscordThreadChannel>> futures = new ArrayList<>();
|
||||||
|
|
||||||
for (Map.Entry<GameChannel, OrDefault<BaseChannelConfig>> entry : channels.entrySet()) {
|
for (Map.Entry<GameChannel, OrDefault<BaseChannelConfig>> entry : channels.entrySet()) {
|
||||||
@ -97,7 +98,7 @@ public class DiscordMessageMirroringModule extends AbstractModule<DiscordSRV> {
|
|||||||
for (Long channelId : channelIds) {
|
for (Long channelId : channelIds) {
|
||||||
discordSRV.discordAPI().getTextChannelById(channelId).ifPresent(textChannel -> {
|
discordSRV.discordAPI().getTextChannelById(channelId).ifPresent(textChannel -> {
|
||||||
if (textChannel.getId() != channel.getId()) {
|
if (textChannel.getId() != channel.getId()) {
|
||||||
mirrorChannels.add(textChannel);
|
mirrorChannels.add(Pair.of(textChannel, config));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -105,43 +106,34 @@ public class DiscordMessageMirroringModule extends AbstractModule<DiscordSRV> {
|
|||||||
|
|
||||||
discordSRV.discordAPI().findOrCreateThreads(iChannelConfig, threadChannel -> {
|
discordSRV.discordAPI().findOrCreateThreads(iChannelConfig, threadChannel -> {
|
||||||
if (threadChannel.getId() != channel.getId()) {
|
if (threadChannel.getId() != channel.getId()) {
|
||||||
mirrorChannels.add(threadChannel);
|
mirrorChannels.add(Pair.of(threadChannel, config));
|
||||||
}
|
}
|
||||||
}, futures);
|
}, futures);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).whenComplete((v, t) -> {
|
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).whenComplete((v, t) -> {
|
||||||
List<DiscordTextChannel> text = new ArrayList<>();
|
List<CompletableFuture<Pair<ReceivedDiscordMessage, OrDefault<MirroringConfig>>>> messageFutures = new ArrayList<>();
|
||||||
List<DiscordThreadChannel> thread = new ArrayList<>();
|
for (Pair<DiscordMessageChannel, OrDefault<MirroringConfig>> pair : mirrorChannels) {
|
||||||
for (DiscordMessageChannel mirrorChannel : mirrorChannels) {
|
DiscordMessageChannel mirrorChannel = pair.getKey();
|
||||||
if (mirrorChannel instanceof DiscordTextChannel) {
|
OrDefault<MirroringConfig> config = pair.getValue();
|
||||||
text.add((DiscordTextChannel) mirrorChannel);
|
SendableDiscordMessage sendableMessage = convert(event.getDiscordMessage(), config);
|
||||||
} else if (mirrorChannel instanceof DiscordThreadChannel) {
|
|
||||||
thread.add((DiscordThreadChannel) mirrorChannel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SendableDiscordMessage.Builder builder = convert(event.getDiscordMessage());
|
CompletableFuture<Pair<ReceivedDiscordMessage, OrDefault<MirroringConfig>>> future =
|
||||||
List<CompletableFuture<ReceivedDiscordMessage>> messageFutures = new ArrayList<>();
|
mirrorChannel.sendMessage(sendableMessage).thenApply(msg -> Pair.of(msg, config));
|
||||||
if (!text.isEmpty()) {
|
|
||||||
SendableDiscordMessage finalMessage = builder.build();
|
messageFutures.add(future);
|
||||||
for (DiscordTextChannel textChannel : text) {
|
future.exceptionally(t2 -> {
|
||||||
messageFutures.add(textChannel.sendMessage(finalMessage));
|
discordSRV.logger().error("Failed to mirror message to " + mirrorChannel, t2);
|
||||||
}
|
return null;
|
||||||
}
|
});
|
||||||
if (!thread.isEmpty()) {
|
|
||||||
SendableDiscordMessage finalMessage = builder.convertToNonWebhook().build();
|
|
||||||
for (DiscordThreadChannel threadChannel : thread) {
|
|
||||||
messageFutures.add(threadChannel.sendMessage(finalMessage));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CompletableFutureUtil.combine(messageFutures).whenComplete((messages, t2) -> {
|
CompletableFutureUtil.combine(messageFutures).whenComplete((messages, t2) -> {
|
||||||
Set<MessageReference> references = new HashSet<>();
|
Set<MessageReference> references = new HashSet<>();
|
||||||
for (ReceivedDiscordMessage msg : messages) {
|
for (Pair<ReceivedDiscordMessage, OrDefault<MirroringConfig>> pair : messages) {
|
||||||
references.add(getReference(msg));
|
references.add(getReference(pair.getKey(), pair.getValue()));
|
||||||
}
|
}
|
||||||
mapping.put(getReference(message), references);
|
mapping.put(getReference(message, null), references);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -149,47 +141,29 @@ public class DiscordMessageMirroringModule extends AbstractModule<DiscordSRV> {
|
|||||||
@Subscribe
|
@Subscribe
|
||||||
public void onDiscordMessageUpdate(DiscordMessageUpdateEvent event) {
|
public void onDiscordMessageUpdate(DiscordMessageUpdateEvent event) {
|
||||||
ReceivedDiscordMessage message = event.getMessage();
|
ReceivedDiscordMessage message = event.getMessage();
|
||||||
Set<MessageReference> references = mapping.get(getReference(message), k -> null);
|
Set<MessageReference> references = mapping.get(getReference(message, null), k -> null);
|
||||||
if (references == null) {
|
if (references == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<DiscordTextChannel, MessageReference> text = new LinkedHashMap<>();
|
|
||||||
Map<DiscordThreadChannel, MessageReference> thread = new LinkedHashMap<>();
|
|
||||||
for (MessageReference reference : references) {
|
for (MessageReference reference : references) {
|
||||||
DiscordMessageChannel channel = reference.getMessageChannel(discordSRV);
|
DiscordMessageChannel channel = reference.getMessageChannel(discordSRV);
|
||||||
if (channel instanceof DiscordTextChannel) {
|
if (channel == null) {
|
||||||
text.put((DiscordTextChannel) channel, reference);
|
continue;
|
||||||
} else if (channel instanceof DiscordThreadChannel) {
|
|
||||||
thread.put((DiscordThreadChannel) channel, reference);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SendableDiscordMessage.Builder builder = convert(message);
|
|
||||||
if (!text.isEmpty()) {
|
|
||||||
SendableDiscordMessage finalMessage = builder.build();
|
|
||||||
for (Map.Entry<DiscordTextChannel, MessageReference> entry : text.entrySet()) {
|
|
||||||
entry.getKey().editMessageById(entry.getValue().messageId, finalMessage).whenComplete((v, t) -> {
|
|
||||||
if (t != null) {
|
|
||||||
discordSRV.logger().error("Failed to update mirrored message in " + entry.getKey());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!thread.isEmpty()) {
|
|
||||||
SendableDiscordMessage finalMessage = builder.convertToNonWebhook().build();
|
|
||||||
for (Map.Entry<DiscordThreadChannel, MessageReference> entry : thread.entrySet()) {
|
|
||||||
entry.getKey().editMessageById(entry.getValue().messageId, finalMessage).whenComplete((v, t) -> {
|
|
||||||
if (t != null) {
|
|
||||||
discordSRV.logger().error("Failed to update mirrored message in " + entry.getKey());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SendableDiscordMessage sendableMessage = convert(message, reference.config);
|
||||||
|
channel.editMessageById(reference.messageId, sendableMessage).whenComplete((v, t) -> {
|
||||||
|
if (t != null) {
|
||||||
|
discordSRV.logger().error("Failed to update mirrored message in " + channel);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onDiscordMessageDelete(DiscordMessageDeleteEvent event) {
|
public void onDiscordMessageDelete(DiscordMessageDeleteEvent event) {
|
||||||
Set<MessageReference> references = mapping.get(getReference(event.getChannel(), event.getMessageId(), false), k -> null);
|
Set<MessageReference> references = mapping.get(getReference(event.getChannel(), event.getMessageId(), false, null), k -> null);
|
||||||
if (references == null) {
|
if (references == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -208,33 +182,50 @@ public class DiscordMessageMirroringModule extends AbstractModule<DiscordSRV> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SendableDiscordMessage.Builder convert(ReceivedDiscordMessage message) {
|
/**
|
||||||
|
* Converts a given received message to a sendable message.
|
||||||
|
*/
|
||||||
|
private SendableDiscordMessage convert(ReceivedDiscordMessage message, OrDefault<MirroringConfig> config) {
|
||||||
DiscordGuildMember member = message.getMember().orElse(null);
|
DiscordGuildMember member = message.getMember().orElse(null);
|
||||||
DiscordUser user = message.getAuthor();
|
DiscordUser user = message.getAuthor();
|
||||||
|
String username = discordSRV.placeholderService().replacePlaceholders(
|
||||||
|
config.get(cfg -> cfg.usernameFormat, "%user_effective_name% [M]"),
|
||||||
|
member, user
|
||||||
|
);
|
||||||
|
if (username.length() > 32) {
|
||||||
|
username = username.substring(0, 32);
|
||||||
|
}
|
||||||
|
|
||||||
SendableDiscordMessage.Builder builder = SendableDiscordMessage.builder()
|
SendableDiscordMessage.Builder builder = SendableDiscordMessage.builder()
|
||||||
.setContent(message.getContent().orElse(null))
|
.setContent(message.getContent().orElse(null))
|
||||||
.setWebhookUsername(member != null ? member.getEffectiveName() : user.getUsername())
|
.setWebhookUsername(username) // (member != null ? member.getEffectiveName() : user.getUsername()) + " [M]"
|
||||||
.setWebhookAvatarUrl(member != null
|
.setWebhookAvatarUrl(
|
||||||
? member.getEffectiveServerAvatarUrl()
|
member != null
|
||||||
: user.getEffectiveAvatarUrl());
|
? member.getEffectiveServerAvatarUrl()
|
||||||
|
: user.getEffectiveAvatarUrl()
|
||||||
|
);
|
||||||
for (DiscordMessageEmbed embed : message.getEmbeds()) {
|
for (DiscordMessageEmbed embed : message.getEmbeds()) {
|
||||||
builder.addEmbed(embed);
|
builder.addEmbed(embed);
|
||||||
}
|
}
|
||||||
return builder;
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private MessageReference getReference(ReceivedDiscordMessage message) {
|
private MessageReference getReference(ReceivedDiscordMessage message, OrDefault<MirroringConfig> config) {
|
||||||
return getReference(message.getChannel(), message.getId(), message.isWebhookMessage());
|
return getReference(message.getChannel(), message.getId(), message.isWebhookMessage(), config);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MessageReference getReference(DiscordMessageChannel channel, long messageId, boolean webhookMessage) {
|
private MessageReference getReference(
|
||||||
|
DiscordMessageChannel channel,
|
||||||
|
long messageId,
|
||||||
|
boolean webhookMessage,
|
||||||
|
OrDefault<MirroringConfig> config
|
||||||
|
) {
|
||||||
if (channel instanceof DiscordTextChannel) {
|
if (channel instanceof DiscordTextChannel) {
|
||||||
DiscordTextChannel textChannel = (DiscordTextChannel) channel;
|
DiscordTextChannel textChannel = (DiscordTextChannel) channel;
|
||||||
return new MessageReference(textChannel, messageId, webhookMessage);
|
return new MessageReference(textChannel, messageId, webhookMessage, config);
|
||||||
} else if (channel instanceof DiscordThreadChannel) {
|
} else if (channel instanceof DiscordThreadChannel) {
|
||||||
DiscordThreadChannel threadChannel = (DiscordThreadChannel) channel;
|
DiscordThreadChannel threadChannel = (DiscordThreadChannel) channel;
|
||||||
return new MessageReference(threadChannel, messageId, webhookMessage);
|
return new MessageReference(threadChannel, messageId, webhookMessage, config);
|
||||||
}
|
}
|
||||||
throw new IllegalStateException("Unexpected channel type: " + channel.getClass().getName());
|
throw new IllegalStateException("Unexpected channel type: " + channel.getClass().getName());
|
||||||
}
|
}
|
||||||
@ -245,20 +236,38 @@ public class DiscordMessageMirroringModule extends AbstractModule<DiscordSRV> {
|
|||||||
private final long threadId;
|
private final long threadId;
|
||||||
private final long messageId;
|
private final long messageId;
|
||||||
private final boolean webhookMessage;
|
private final boolean webhookMessage;
|
||||||
|
private final OrDefault<MirroringConfig> config;
|
||||||
|
|
||||||
public MessageReference(DiscordTextChannel textChannel, long messageId, boolean webhookMessage) {
|
public MessageReference(
|
||||||
this(textChannel.getId(), -1L, messageId, webhookMessage);
|
DiscordTextChannel textChannel,
|
||||||
|
long messageId,
|
||||||
|
boolean webhookMessage,
|
||||||
|
OrDefault<MirroringConfig> config
|
||||||
|
) {
|
||||||
|
this(textChannel.getId(), -1L, messageId, webhookMessage, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MessageReference(DiscordThreadChannel threadChannel, long messageId, boolean webhookMessage) {
|
public MessageReference(
|
||||||
this(threadChannel.getParentChannel().getId(), threadChannel.getId(), messageId, webhookMessage);
|
DiscordThreadChannel threadChannel,
|
||||||
|
long messageId,
|
||||||
|
boolean webhookMessage,
|
||||||
|
OrDefault<MirroringConfig> config
|
||||||
|
) {
|
||||||
|
this(threadChannel.getParentChannel().getId(), threadChannel.getId(), messageId, webhookMessage, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MessageReference(long channelId, long threadId, long messageId, boolean webhookMessage) {
|
public MessageReference(
|
||||||
|
long channelId,
|
||||||
|
long threadId,
|
||||||
|
long messageId,
|
||||||
|
boolean webhookMessage,
|
||||||
|
OrDefault<MirroringConfig> config
|
||||||
|
) {
|
||||||
this.channelId = channelId;
|
this.channelId = channelId;
|
||||||
this.threadId = threadId;
|
this.threadId = threadId;
|
||||||
this.messageId = messageId;
|
this.messageId = messageId;
|
||||||
this.webhookMessage = webhookMessage;
|
this.webhookMessage = webhookMessage;
|
||||||
|
this.config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DiscordMessageChannel getMessageChannel(DiscordSRV discordSRV) {
|
public DiscordMessageChannel getMessageChannel(DiscordSRV discordSRV) {
|
||||||
|
@ -162,32 +162,14 @@ public class MinecraftToDiscordChatModule extends AbstractGameMessageModule<Mine
|
|||||||
.sorted(Comparator.comparingInt(mention -> ((CachedMention) mention).searchLength).reversed())
|
.sorted(Comparator.comparingInt(mention -> ((CachedMention) mention).searchLength).reversed())
|
||||||
.forEachOrdered(mention -> channelMessagePlaceholders.replaceAll(mention.search, mention.mention));
|
.forEachOrdered(mention -> channelMessagePlaceholders.replaceAll(mention.search, mention.mention));
|
||||||
|
|
||||||
SendableDiscordMessage.Formatter discordMessage = format.toFormatter()
|
SendableDiscordMessage discordMessage = format.toFormatter()
|
||||||
.addContext(context)
|
.addContext(context)
|
||||||
.addReplacement("%message%", new FormattedText(channelMessagePlaceholders.toString()))
|
.addReplacement("%message%", new FormattedText(channelMessagePlaceholders.toString()))
|
||||||
.applyPlaceholderService();
|
.applyPlaceholderService()
|
||||||
|
.build();
|
||||||
|
|
||||||
List<DiscordMessageChannel> text = new ArrayList<>();
|
|
||||||
List<DiscordMessageChannel> thread = new ArrayList<>();
|
|
||||||
for (DiscordMessageChannel channel : entry.getValue()) {
|
for (DiscordMessageChannel channel : entry.getValue()) {
|
||||||
if (channel instanceof DiscordTextChannel) {
|
futures.put(channel.sendMessage(discordMessage), channel);
|
||||||
text.add(channel);
|
|
||||||
} else if (channel instanceof DiscordThreadChannel) {
|
|
||||||
thread.add(channel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!text.isEmpty()) {
|
|
||||||
SendableDiscordMessage finalMessage = discordMessage.build();
|
|
||||||
for (DiscordMessageChannel channel : text) {
|
|
||||||
futures.put(channel.sendMessage(finalMessage), channel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!thread.isEmpty()) {
|
|
||||||
SendableDiscordMessage finalMessage = discordMessage.convertToNonWebhook().build();
|
|
||||||
for (DiscordMessageChannel channel : thread) {
|
|
||||||
futures.put(channel.sendMessage(finalMessage), channel);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user