Merge branch 'main' into profiles

This commit is contained in:
Vankka 2022-02-19 22:47:47 +02:00
commit 21045f7bb2
No known key found for this signature in database
GPG Key ID: 6E50CB7A29B96AD0
26 changed files with 361 additions and 268 deletions

View File

@ -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);
}

View File

@ -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.

View File

@ -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.

View File

@ -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);
}

View File

@ -9,7 +9,7 @@ version '2.0.0-SNAPSHOT'
ext { ext {
// DependencyDownload (change plugin version above) // DependencyDownload (change plugin version above)
ddVersion = '1.1.5-SNAPSHOT' ddVersion = '1.2.2-SNAPSHOT'
// MinecraftDependencyDownload // MinecraftDependencyDownload
mddVersion = '1.0.0-SNAPSHOT' mddVersion = '1.0.0-SNAPSHOT'
// JDA // JDA
@ -48,13 +48,20 @@ allprojects {
repositories { repositories {
// Snapshot repositories // Snapshot repositories
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } //maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
maven { url 'https://s01.oss.sonatype.org/content/repositories/snapshots/' } maven { url 'https://s01.oss.sonatype.org/content/repositories/snapshots/' }
//mavenLocal()
mavenLocal() maven {
url 'https://nexus.scarsz.me/content/groups/public/'
content {
includeGroup 'github.scarsz'
includeGroup 'me.scarsz'
}
}
// Get dependencies from central last, everything else should be filtered
mavenCentral() mavenCentral()
maven { url 'https://nexus.scarsz.me/content/groups/public/' }
} }
dependencies { dependencies {

View File

@ -2,31 +2,47 @@ apply from: rootProject.file('buildscript/runtime.gradle')
allprojects { allprojects {
repositories { repositories {
maven { url 'https://papermc.io/repo/repository/maven-public/' } exclusiveContent {
forRepository {
maven { url 'https://papermc.io/repo/repository/maven-public/' }
}
filter {
includeGroup 'com.destroystokyo.paper'
}
}
exclusiveContent {
forRepository {
maven { url 'https://nexus.scarsz.me/content/groups/public/' }
}
filter {
includeGroup 'net.milkbowl.vault'
}
}
} }
dependencies { dependencies {
// API
annotationProcessor project(':api')
// Platform // Platform
compileOnly 'com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT' compileOnly 'com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT'
} }
} }
dependencies { dependencies {
// API
annotationProcessor project(':api')
// Common // Common
compileOnly project(':common:common-server') compileOnly project(':common:common-server')
implementation project(path: ':common:common-server', configuration: 'runtimeElements') implementation project(path: ':common:common-server', configuration: 'runtimeElements')
// DependencyDownload // DependencyDownload
implementation 'dev.vankka.minecraftdependencydownload:bukkit:' + rootProject.mddVersion implementation 'dev.vankka:minecraftdependencydownload-bukkit:' + rootProject.mddVersion
// Adventure // Adventure
runtimeDownloadApi 'net.kyori:adventure-platform-bukkit:' + rootProject.adventurePlatformVersion runtimeDownloadApi 'net.kyori:adventure-platform-bukkit:' + rootProject.adventurePlatformVersion
// Integrations // Integrations
compileOnly "com.github.MilkBowl:VaultAPI:1.7" compileOnly 'net.milkbowl.vault:VaultAPI:1.7'
} }
shadowJar { shadowJar {

View File

@ -7,7 +7,7 @@ dependencies {
implementation project(':common:common-api') implementation project(':common:common-api')
// DependencyDownload // DependencyDownload
implementation 'dev.vankka.minecraftdependencydownload:bukkit-loader:' + rootProject.mddVersion implementation 'dev.vankka:minecraftdependencydownload-bukkit-loader:' + rootProject.mddVersion
} }
processResources { processResources {

View File

@ -2,24 +2,31 @@ apply from: rootProject.file('buildscript/runtime.gradle')
allprojects { allprojects {
repositories { repositories {
maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } exclusiveContent {
forRepository {
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
}
filter {
includeGroup 'net.md-5'
}
}
} }
dependencies { dependencies {
// API
annotationProcessor project(':api')
// Platform // Platform
compileOnly 'net.md-5:bungeecord-api:1.17-R0.1-SNAPSHOT' compileOnly 'net.md-5:bungeecord-api:1.17-R0.1-SNAPSHOT'
} }
} }
dependencies { dependencies {
// API
annotationProcessor project(':api')
// Common // Common
implementation project(':common:common-proxy') implementation project(':common:common-proxy')
// DependencyDownload // DependencyDownload
implementation 'dev.vankka.minecraftdependencydownload:bungee:' + rootProject.mddVersion implementation 'dev.vankka:minecraftdependencydownload-bungee:' + rootProject.mddVersion
// Adventure // Adventure
runtimeDownloadApi 'net.kyori:adventure-platform-bungeecord:' + rootProject.adventurePlatformVersion runtimeDownloadApi 'net.kyori:adventure-platform-bungeecord:' + rootProject.adventurePlatformVersion

View File

@ -7,7 +7,7 @@ dependencies {
implementation project(':common:common-api') implementation project(':common:common-api')
// DependencyDownload // DependencyDownload
implementation 'dev.vankka.minecraftdependencydownload:bungee-loader:' + rootProject.mddVersion implementation 'dev.vankka:minecraftdependencydownload-bungee-loader:' + rootProject.mddVersion
} }
processResources { processResources {

View File

@ -32,10 +32,10 @@ dependencies {
testImplementation project(':common:common-api') testImplementation project(':common:common-api')
// DependencyDownload // DependencyDownload
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'

View File

@ -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]";
} }

View File

@ -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()
)); ));
} }

View File

@ -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));

View File

@ -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());
} }

View File

@ -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))
);
}
}

View File

@ -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;

View File

@ -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) {

View File

@ -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);

View File

@ -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

View File

@ -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();

View File

@ -37,6 +37,7 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
public class DiscordSRVLogger implements Logger { public class DiscordSRVLogger implements Logger {
@ -47,6 +48,7 @@ public class DiscordSRVLogger implements Logger {
private final DiscordSRV discordSRV; private final DiscordSRV discordSRV;
private final Path logsDirectory; private final Path logsDirectory;
private final List<Path> debugLogs; private final List<Path> debugLogs;
private final ReentrantLock debugLogLock = new ReentrantLock();
public DiscordSRVLogger(DiscordSRV discordSRV) { public DiscordSRVLogger(DiscordSRV discordSRV) {
this.discordSRV = discordSRV; this.discordSRV = discordSRV;
@ -126,14 +128,6 @@ public class DiscordSRVLogger implements Logger {
private void writeToFile(String loggerName, Path path, long time, LogLevel logLevel, String message, Throwable throwable) { private void writeToFile(String loggerName, Path path, long time, LogLevel logLevel, String message, Throwable throwable) {
try { try {
Path parent = path.getParent();
if (!Files.exists(parent)) {
Files.createDirectories(parent);
}
if (!Files.exists(path)) {
Files.createFile(path);
}
if (message == null) { if (message == null) {
message = ""; message = "";
} }
@ -147,7 +141,22 @@ public class DiscordSRVLogger implements Logger {
line += ExceptionUtils.getStackTrace(throwable) + "\n"; line += ExceptionUtils.getStackTrace(throwable) + "\n";
} }
Files.write(path, line.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); synchronized (debugLogLock) {
try {
debugLogLock.lock();
Path parent = path.getParent();
if (!Files.exists(parent)) {
Files.createDirectories(parent);
}
if (!Files.exists(path)) {
Files.createFile(path);
}
Files.write(path, line.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
} finally {
debugLogLock.unlock();
}
}
} catch (Throwable e) { } catch (Throwable e) {
// Prevent infinite loop // Prevent infinite loop
discordSRV.platformLogger().error("Failed to write to debug log", e); discordSRV.platformLogger().error("Failed to write to debug log", e);

View File

@ -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) {

View File

@ -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);
}
} }
} }

View File

@ -3,13 +3,17 @@ apply from: rootProject.file('buildscript/runtime.gradle')
var spongeVersion = '8.0.0' var spongeVersion = '8.0.0'
allprojects { allprojects {
repositories { repositories {
maven { url 'https://repo.spongepowered.org/maven/' } exclusiveContent {
forRepository {
maven { url 'https://repo.spongepowered.org/maven/' }
}
filter {
includeGroup 'org.spongepowered'
}
}
} }
dependencies { dependencies {
// API
annotationProcessor project(':api')
// Platform // Platform
annotationProcessor 'org.spongepowered:spongeapi:' + spongeVersion annotationProcessor 'org.spongepowered:spongeapi:' + spongeVersion
compileOnly 'org.spongepowered:spongeapi:' + spongeVersion compileOnly 'org.spongepowered:spongeapi:' + spongeVersion
@ -17,11 +21,14 @@ allprojects {
} }
dependencies { dependencies {
// API
annotationProcessor project(':api')
// Common // Common
implementation project(':common:common-server') implementation project(':common:common-server')
// Dependency Download // Dependency Download
implementation 'dev.vankka.minecraftdependencydownload:jarinjar-bootstrap:' + rootProject.mddVersion implementation 'dev.vankka:dependencydownload-jarinjar-bootstrap:' + rootProject.ddVersion
compileOnlyApi project(':sponge:sponge-loader') compileOnlyApi project(':sponge:sponge-loader')
} }

View File

@ -12,7 +12,7 @@ dependencies {
implementation project(':common:common-api') implementation project(':common:common-api')
// DependencyDownload // DependencyDownload
implementation 'dev.vankka.minecraftdependencydownload:jarinjar-loader:' + rootProject.mddVersion implementation 'dev.vankka:dependencydownload-jarinjar-loader:' + rootProject.ddVersion
} }
shadowJar { shadowJar {

View File

@ -2,7 +2,14 @@ apply from: rootProject.file('buildscript/standalone.gradle')
apply plugin: 'net.kyori.blossom' apply plugin: 'net.kyori.blossom'
repositories { repositories {
maven { url 'https://nexus.velocitypowered.com/repository/maven-public/' } exclusiveContent {
forRepository {
maven { url 'https://nexus.velocitypowered.com/repository/maven-public/' }
}
filter {
includeGroup 'com.velocitypowered'
}
}
} }
var velocityVersion = '3.0.0' var velocityVersion = '3.0.0'