mirror of
https://github.com/DiscordSRV/Ascension.git
synced 2024-12-25 17:08:27 +01:00
Join, leave, server switch messages. Fixed dependency logging, added config option ordering annotation, fixed some issues with translation/configuration
This commit is contained in:
parent
9ffce74061
commit
0e73f80d40
4
.github/workflows/crowdin-download.yaml
vendored
4
.github/workflows/crowdin-download.yaml
vendored
@ -19,8 +19,8 @@ jobs:
|
||||
create_pull_request: true
|
||||
pull_request_title: "New Crowdin translations"
|
||||
pull_request_body: ""
|
||||
source: "source.yml"
|
||||
translation: "/%original_path%/src/main/resources/translations/%three_letters_code%.yml"
|
||||
source: "source.yaml"
|
||||
translation: "/%original_path%/src/main/resources/translations/%three_letters_code%.yaml"
|
||||
project_id: ${{ secrets.CROWDIN_PROJECT_ID }}
|
||||
token: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
|
||||
env:
|
||||
|
4
.github/workflows/crowdin-upload.yaml
vendored
4
.github/workflows/crowdin-upload.yaml
vendored
@ -27,8 +27,8 @@ jobs:
|
||||
upload_translations: true
|
||||
download_translations: false
|
||||
localization_branch_name: i18n
|
||||
source: "source.yml"
|
||||
translation: "/%original_path%/src/main/resources/translations/%three_letters_code%.yml"
|
||||
source: "source.yaml"
|
||||
translation: "/%original_path%/src/main/resources/translations/%three_letters_code%.yaml"
|
||||
project_id: ${{ secrets.CROWDIN_PROJECT_ID }}
|
||||
token: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
|
||||
env:
|
||||
|
@ -67,7 +67,7 @@ public class Color {
|
||||
}
|
||||
|
||||
public String hex() {
|
||||
return Integer.toHexString(rgb);
|
||||
return Integer.toHexString(0xF000000 | rgb).substring(1);
|
||||
}
|
||||
|
||||
public int red() {
|
||||
|
@ -429,7 +429,7 @@ public class DiscordMessageEmbed {
|
||||
@NotNull
|
||||
public Builder setFooter(@Nullable CharSequence footer, @Nullable CharSequence footerImageUrl) {
|
||||
this.footer = footer != null ? footer.toString() : null;
|
||||
this.footerImageUrl = footerImageUrl != null ? footerImageUrl.toString() : null;
|
||||
this.footerImageUrl = footerImageUrl != null && footerImageUrl.length() != 0 ? footerImageUrl.toString() : null;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,7 @@ public class SendableDiscordMessageImpl implements SendableDiscordMessage {
|
||||
|
||||
@Override
|
||||
public @NotNull Formatter applyPlaceholderService() {
|
||||
DiscordSRVApi api = DiscordSRVApiProvider.optional().orElse(null);
|
||||
DiscordSRVApi api = DiscordSRVApiProvider.get();
|
||||
if (api == null) {
|
||||
throw new IllegalStateException("DiscordSRVApi not available");
|
||||
}
|
||||
@ -221,7 +221,7 @@ public class SendableDiscordMessageImpl implements SendableDiscordMessage {
|
||||
private Function<Matcher, Object> wrapFunction(Function<Matcher, Object> function) {
|
||||
return matcher -> {
|
||||
Object result = function.apply(matcher);
|
||||
if (result instanceof FormattedText) {
|
||||
if (result instanceof FormattedText || ResultMappers.isPlainContext()) {
|
||||
// Process as regular text
|
||||
return result.toString();
|
||||
} else if (result instanceof CharSequence) {
|
||||
@ -258,7 +258,7 @@ public class SendableDiscordMessageImpl implements SendableDiscordMessage {
|
||||
DiscordMessageEmbed.Builder embedBuilder = embed.toBuilder();
|
||||
|
||||
// TODO: check which parts allow formatting more thoroughly
|
||||
ResultMappers.runInPlainComponentContext(() -> {
|
||||
ResultMappers.runInPlainContext(() -> {
|
||||
embedBuilder.setAuthor(
|
||||
placeholders.apply(
|
||||
embedBuilder.getAuthorName()),
|
||||
@ -307,7 +307,7 @@ public class SendableDiscordMessageImpl implements SendableDiscordMessage {
|
||||
builder.addEmbed(embedBuilder.build());
|
||||
}
|
||||
|
||||
ResultMappers.runInPlainComponentContext(() -> {
|
||||
ResultMappers.runInPlainContext(() -> {
|
||||
builder.setWebhookUsername(placeholders.apply(builder.getWebhookUsername()));
|
||||
builder.setWebhookAvatarUrl(placeholders.apply(builder.getWebhookAvatarUrl()));
|
||||
});
|
||||
|
@ -21,7 +21,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.discordsrv.api.event.events.discord;
|
||||
package com.discordsrv.api.discord.events;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.channel.DiscordDMChannel;
|
||||
import com.discordsrv.api.discord.api.entity.channel.DiscordMessageChannel;
|
@ -25,6 +25,7 @@ package com.discordsrv.api.event.bus;
|
||||
|
||||
import com.discordsrv.api.event.events.Event;
|
||||
import net.dv8tion.jda.api.events.GenericEvent;
|
||||
import org.jetbrains.annotations.Blocking;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@ -52,6 +53,7 @@ public interface EventBus {
|
||||
*
|
||||
* @param event the event
|
||||
*/
|
||||
@Blocking
|
||||
void publish(@NotNull Event event);
|
||||
|
||||
/**
|
||||
@ -59,6 +61,7 @@ public interface EventBus {
|
||||
*
|
||||
* @param event the event
|
||||
*/
|
||||
@Blocking
|
||||
void publish(@NotNull GenericEvent event);
|
||||
|
||||
}
|
||||
|
@ -28,12 +28,12 @@ import com.discordsrv.api.component.MinecraftComponent;
|
||||
import com.discordsrv.api.event.events.Event;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class DiscordMessageForwardedEvent implements Event {
|
||||
public class DiscordChatMessageForwardedEvent implements Event {
|
||||
|
||||
private final MinecraftComponent message;
|
||||
private final GameChannel channel;
|
||||
|
||||
public DiscordMessageForwardedEvent(@NotNull MinecraftComponent message, @NotNull GameChannel channel) {
|
||||
public DiscordChatMessageForwardedEvent(@NotNull MinecraftComponent message, @NotNull GameChannel channel) {
|
||||
this.message = message;
|
||||
this.channel = channel;
|
||||
}
|
@ -21,4 +21,14 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.discordsrv.api.event.events.message.receive;
|
||||
package com.discordsrv.api.event.events.message.forward.game;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class DeathMessageForwardedEvent extends AbstractGameMessageForwardedEvent {
|
||||
|
||||
public DeathMessageForwardedEvent(@NotNull ReceivedDiscordMessageCluster discordMessage) {
|
||||
super(discordMessage);
|
||||
}
|
||||
}
|
@ -21,4 +21,14 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.discordsrv.api.event.events.message;
|
||||
package com.discordsrv.api.event.events.message.forward.game;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class GameChatMessageForwardedEvent extends AbstractGameMessageForwardedEvent {
|
||||
|
||||
public GameChatMessageForwardedEvent(@NotNull ReceivedDiscordMessageCluster discordMessage) {
|
||||
super(discordMessage);
|
||||
}
|
||||
}
|
@ -26,9 +26,9 @@ package com.discordsrv.api.event.events.message.forward.game;
|
||||
import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ChatMessageForwardedEvent extends AbstractGameMessageForwardedEvent {
|
||||
public class JoinMessageForwardedEvent extends AbstractGameMessageForwardedEvent {
|
||||
|
||||
public ChatMessageForwardedEvent(@NotNull ReceivedDiscordMessageCluster discordMessage) {
|
||||
public JoinMessageForwardedEvent(@NotNull ReceivedDiscordMessageCluster discordMessage) {
|
||||
super(discordMessage);
|
||||
}
|
||||
}
|
@ -21,4 +21,14 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.discordsrv.api.event.events.message.forward;
|
||||
package com.discordsrv.api.event.events.message.forward.game;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class LeaveMessageForwardedEvent extends AbstractGameMessageForwardedEvent {
|
||||
|
||||
public LeaveMessageForwardedEvent(@NotNull ReceivedDiscordMessageCluster discordMessage) {
|
||||
super(discordMessage);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.discordsrv.api.event.events.message.forward.game;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ServerSwitchMessageForwardedEvent extends AbstractGameMessageForwardedEvent {
|
||||
|
||||
public ServerSwitchMessageForwardedEvent(@NotNull ReceivedDiscordMessageCluster discordMessage) {
|
||||
super(discordMessage);
|
||||
}
|
||||
}
|
@ -30,7 +30,7 @@ import com.discordsrv.api.event.events.Cancellable;
|
||||
import com.discordsrv.api.event.events.Processable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class DiscordMessageProcessingEvent implements Cancellable, Processable {
|
||||
public class DiscordChatMessageProcessingEvent implements Cancellable, Processable {
|
||||
|
||||
private final ReceivedDiscordMessage discordMessage;
|
||||
private String messageContent;
|
||||
@ -38,7 +38,7 @@ public class DiscordMessageProcessingEvent implements Cancellable, Processable {
|
||||
private boolean cancelled;
|
||||
private boolean processed;
|
||||
|
||||
public DiscordMessageProcessingEvent(@NotNull ReceivedDiscordMessage discordMessage, @NotNull DiscordTextChannel channel) {
|
||||
public DiscordChatMessageProcessingEvent(@NotNull ReceivedDiscordMessage discordMessage, @NotNull DiscordTextChannel channel) {
|
||||
this.discordMessage = discordMessage;
|
||||
this.messageContent = discordMessage.getContent().orElse(null);
|
||||
this.channel = channel;
|
||||
@ -81,6 +81,9 @@ public class DiscordMessageProcessingEvent implements Cancellable, Processable {
|
||||
|
||||
@Override
|
||||
public void markAsProcessed() {
|
||||
if (isCancelled()) {
|
||||
throw new IllegalStateException("Cannot process cancelled event");
|
||||
}
|
||||
this.processed = true;
|
||||
}
|
||||
|
@ -23,7 +23,6 @@
|
||||
|
||||
package com.discordsrv.api.event.events.message.receive.game;
|
||||
|
||||
import com.discordsrv.api.channel.GameChannel;
|
||||
import com.discordsrv.api.component.MinecraftComponent;
|
||||
import com.discordsrv.api.event.events.Cancellable;
|
||||
import com.discordsrv.api.event.events.Processable;
|
||||
@ -32,30 +31,22 @@ import org.jetbrains.annotations.NotNull;
|
||||
public abstract class AbstractGameMessageReceiveEvent implements Processable, Cancellable {
|
||||
|
||||
private final MinecraftComponent message;
|
||||
private GameChannel gameChannel;
|
||||
private boolean cancelled;
|
||||
private boolean processed;
|
||||
|
||||
public AbstractGameMessageReceiveEvent(@NotNull MinecraftComponent message, @NotNull GameChannel gameChannel, boolean cancelled) {
|
||||
public AbstractGameMessageReceiveEvent(
|
||||
@NotNull MinecraftComponent message,
|
||||
boolean cancelled
|
||||
) {
|
||||
this.message = message;
|
||||
this.gameChannel = gameChannel;
|
||||
this.cancelled = cancelled;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public MinecraftComponent message() {
|
||||
public MinecraftComponent getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public GameChannel getGameChannel() {
|
||||
return gameChannel;
|
||||
}
|
||||
|
||||
public void setGameChannel(@NotNull GameChannel gameChannel) {
|
||||
this.gameChannel = gameChannel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
@ -73,6 +64,9 @@ public abstract class AbstractGameMessageReceiveEvent implements Processable, Ca
|
||||
|
||||
@Override
|
||||
public void markAsProcessed() {
|
||||
if (isCancelled()) {
|
||||
throw new IllegalStateException("Cannot process cancelled event");
|
||||
}
|
||||
this.processed = true;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of the DiscordSRV API, licensed under the MIT License
|
||||
* Copyright (c) 2016-2021 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.event.events.message.receive.game;
|
||||
|
||||
import com.discordsrv.api.channel.GameChannel;
|
||||
import com.discordsrv.api.component.MinecraftComponent;
|
||||
import com.discordsrv.api.player.DiscordSRVPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class DeathMessageReceiveEvent extends AbstractGameMessageReceiveEvent {
|
||||
|
||||
private final DiscordSRVPlayer player;
|
||||
private GameChannel gameChannel;
|
||||
|
||||
public DeathMessageReceiveEvent(
|
||||
@NotNull DiscordSRVPlayer player,
|
||||
@Nullable GameChannel gameChannel,
|
||||
@NotNull MinecraftComponent message,
|
||||
boolean cancelled) {
|
||||
super(message, cancelled);
|
||||
this.player = player;
|
||||
this.gameChannel = gameChannel;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DiscordSRVPlayer getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GameChannel getGameChannel() {
|
||||
return gameChannel;
|
||||
}
|
||||
|
||||
public void setGameChannel(@Nullable GameChannel gameChannel) {
|
||||
this.gameChannel = gameChannel;
|
||||
}
|
||||
}
|
@ -27,14 +27,29 @@ import com.discordsrv.api.channel.GameChannel;
|
||||
import com.discordsrv.api.component.MinecraftComponent;
|
||||
import com.discordsrv.api.event.events.PlayerEvent;
|
||||
import com.discordsrv.api.player.DiscordSRVPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ChatMessageProcessingEvent extends AbstractGameMessageReceiveEvent implements PlayerEvent {
|
||||
public class GameChatMessageReceiveEvent extends AbstractGameMessageReceiveEvent implements PlayerEvent {
|
||||
|
||||
private final DiscordSRVPlayer player;
|
||||
private GameChannel gameChannel;
|
||||
|
||||
public ChatMessageProcessingEvent(DiscordSRVPlayer player, MinecraftComponent message, GameChannel gameChannel, boolean cancelled) {
|
||||
super(message, gameChannel, cancelled);
|
||||
public GameChatMessageReceiveEvent(
|
||||
@NotNull DiscordSRVPlayer player,
|
||||
@NotNull GameChannel gameChannel,
|
||||
@NotNull MinecraftComponent message,
|
||||
boolean cancelled) {
|
||||
super(message, cancelled);
|
||||
this.player = player;
|
||||
this.gameChannel = gameChannel;
|
||||
}
|
||||
|
||||
public GameChannel getGameChannel() {
|
||||
return gameChannel;
|
||||
}
|
||||
|
||||
public void setGameChannel(GameChannel gameChannel) {
|
||||
this.gameChannel = gameChannel;
|
||||
}
|
||||
|
||||
@Override
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* This file is part of the DiscordSRV API, licensed under the MIT License
|
||||
* Copyright (c) 2016-2021 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.event.events.message.receive.game;
|
||||
|
||||
import com.discordsrv.api.channel.GameChannel;
|
||||
import com.discordsrv.api.component.MinecraftComponent;
|
||||
import com.discordsrv.api.player.DiscordSRVPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class JoinMessageReceiveEvent extends AbstractGameMessageReceiveEvent {
|
||||
|
||||
private final DiscordSRVPlayer player;
|
||||
private GameChannel gameChannel;
|
||||
|
||||
public JoinMessageReceiveEvent(
|
||||
@NotNull DiscordSRVPlayer player,
|
||||
@Nullable GameChannel gameChannel,
|
||||
@NotNull MinecraftComponent message,
|
||||
boolean cancelled) {
|
||||
super(message, cancelled);
|
||||
this.player = player;
|
||||
this.gameChannel = gameChannel;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DiscordSRVPlayer getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GameChannel getGameChannel() {
|
||||
return gameChannel;
|
||||
}
|
||||
|
||||
public void setGameChannel(@Nullable GameChannel gameChannel) {
|
||||
this.gameChannel = gameChannel;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* This file is part of the DiscordSRV API, licensed under the MIT License
|
||||
* Copyright (c) 2016-2021 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.event.events.message.receive.game;
|
||||
|
||||
import com.discordsrv.api.channel.GameChannel;
|
||||
import com.discordsrv.api.component.MinecraftComponent;
|
||||
import com.discordsrv.api.player.DiscordSRVPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class LeaveMessageReceiveEvent extends AbstractGameMessageReceiveEvent {
|
||||
|
||||
private final DiscordSRVPlayer player;
|
||||
private GameChannel gameChannel;
|
||||
|
||||
public LeaveMessageReceiveEvent(
|
||||
@NotNull DiscordSRVPlayer player,
|
||||
@Nullable GameChannel gameChannel,
|
||||
@NotNull MinecraftComponent message,
|
||||
boolean cancelled) {
|
||||
super(message, cancelled);
|
||||
this.player = player;
|
||||
this.gameChannel = gameChannel;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DiscordSRVPlayer getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GameChannel getGameChannel() {
|
||||
return gameChannel;
|
||||
}
|
||||
|
||||
public void setGameChannel(@Nullable GameChannel gameChannel) {
|
||||
this.gameChannel = gameChannel;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.discordsrv.api.event.events.message.receive.game;
|
||||
|
||||
import com.discordsrv.api.component.MinecraftComponent;
|
||||
import com.discordsrv.api.player.DiscordSRVPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ServerSwitchMessageReceiveEvent extends AbstractGameMessageReceiveEvent {
|
||||
|
||||
private final DiscordSRVPlayer player;
|
||||
|
||||
public ServerSwitchMessageReceiveEvent(DiscordSRVPlayer player, @NotNull MinecraftComponent message, boolean cancelled) {
|
||||
super(message, cancelled);
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public DiscordSRVPlayer getPlayer() {
|
||||
return player;
|
||||
}
|
||||
}
|
@ -29,22 +29,21 @@ import java.util.function.Supplier;
|
||||
|
||||
public final class ResultMappers {
|
||||
|
||||
private static final ThreadLocal<Boolean> PLAIN_COMPONENTS = ThreadLocal.withInitial(() -> false);
|
||||
private static final ThreadLocal<Boolean> PLAIN = ThreadLocal.withInitial(() -> false);
|
||||
|
||||
private ResultMappers() {}
|
||||
|
||||
public static boolean isPlainComponentContext() {
|
||||
return PLAIN_COMPONENTS.get();
|
||||
public static boolean isPlainContext() {
|
||||
return PLAIN.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to run the provided {@link Runnable} where {@link PlaceholderService}s
|
||||
* will replace {@link com.discordsrv.api.component.MinecraftComponent}s
|
||||
* as plain without formatting (instead of converting to Discord formatting).
|
||||
* will use plain text without Discord formatting (instead of converting to Discord formatting).
|
||||
* @param runnable a task that will be executed immediately
|
||||
*/
|
||||
public static void runInPlainComponentContext(Runnable runnable) {
|
||||
getInPlainComponentContext(() -> {
|
||||
public static void runInPlainContext(Runnable runnable) {
|
||||
getInPlainContext(() -> {
|
||||
runnable.run();
|
||||
return null;
|
||||
});
|
||||
@ -52,15 +51,14 @@ public final class ResultMappers {
|
||||
|
||||
/**
|
||||
* Utility method to run the provided {@link Runnable} where {@link PlaceholderService}s
|
||||
* will replace {@link com.discordsrv.api.component.MinecraftComponent}s
|
||||
* as plain without formatting (instead of converting to Discord formatting).
|
||||
* will use plain text without Discord formatting (instead of converting to Discord formatting).
|
||||
* @param supplier a supplier that will be executed immediately
|
||||
* @return the output of the supplier provided as parameter
|
||||
*/
|
||||
public static <T> T getInPlainComponentContext(Supplier<T> supplier) {
|
||||
PLAIN_COMPONENTS.set(true);
|
||||
public static <T> T getInPlainContext(Supplier<T> supplier) {
|
||||
PLAIN.set(true);
|
||||
T output = supplier.get();
|
||||
PLAIN_COMPONENTS.set(false);
|
||||
PLAIN.set(false);
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ public interface DiscordSRVPlayer {
|
||||
*/
|
||||
@Placeholder("player_name")
|
||||
@NotNull
|
||||
String getUsername();
|
||||
String username();
|
||||
|
||||
/**
|
||||
* The {@link UUID} of the player.
|
||||
@ -47,6 +47,6 @@ public interface DiscordSRVPlayer {
|
||||
*/
|
||||
@Placeholder("player_uuid")
|
||||
@NotNull
|
||||
UUID getUniqueId();
|
||||
UUID uniqueId();
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id 'com.github.johnrengelman.shadow' version '7.0.0' apply false
|
||||
id 'com.github.johnrengelman.shadow' version '7.1.1' apply false
|
||||
id 'org.cadixdev.licenser' version '0.6.0' apply false
|
||||
id 'io.freefair.lombok' version '5.3.3.3' apply false
|
||||
id 'net.kyori.blossom' version '1.2.0' apply false
|
||||
|
@ -40,6 +40,9 @@ shadowJar {
|
||||
// Commons
|
||||
'org.apache.commons',
|
||||
|
||||
// SLF4J
|
||||
'org.slf4j',
|
||||
|
||||
// Checker Framework
|
||||
'org.checkerframework',
|
||||
|
||||
@ -54,10 +57,6 @@ shadowJar {
|
||||
relocate it, 'com.discordsrv.dependencies.' + it
|
||||
}
|
||||
|
||||
// SLF4J
|
||||
relocate('org.slf4j', 'com.discordsrv.dependencies.org.slf4j') {
|
||||
include('*')
|
||||
exclude('com.discordsrv.logging.impl.SLF4JLoggerImpl')
|
||||
exclude('com.discordsrv.velocity.DiscordSRVVelocityBootstrap')
|
||||
}
|
||||
// SLF4J hack
|
||||
relocate('com.discordsrv.x.slf4j', 'org.slf4j')
|
||||
}
|
||||
|
@ -25,11 +25,13 @@ import com.discordsrv.bukkit.config.manager.BukkitConfigManager;
|
||||
import com.discordsrv.bukkit.config.manager.BukkitConnectionConfigManager;
|
||||
import com.discordsrv.bukkit.console.BukkitConsole;
|
||||
import com.discordsrv.bukkit.listener.BukkitChatListener;
|
||||
import com.discordsrv.bukkit.listener.BukkitDeathListener;
|
||||
import com.discordsrv.bukkit.listener.BukkitStatusMessageListener;
|
||||
import com.discordsrv.bukkit.player.BukkitPlayerProvider;
|
||||
import com.discordsrv.bukkit.scheduler.BukkitScheduler;
|
||||
import com.discordsrv.common.config.manager.ConnectionConfigManager;
|
||||
import com.discordsrv.common.config.manager.MainConfigManager;
|
||||
import com.discordsrv.logging.Logger;
|
||||
import com.discordsrv.common.logging.Logger;
|
||||
import com.discordsrv.common.server.ServerDiscordSRV;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import org.bukkit.Server;
|
||||
@ -133,5 +135,7 @@ public class BukkitDiscordSRV extends ServerDiscordSRV<BukkitConfig, BukkitConne
|
||||
|
||||
// Register listeners
|
||||
server().getPluginManager().registerEvents(BukkitChatListener.get(this), plugin());
|
||||
server().getPluginManager().registerEvents(new BukkitDeathListener(this), plugin());
|
||||
server().getPluginManager().registerEvents(new BukkitStatusMessageListener(this), plugin());
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,8 @@
|
||||
package com.discordsrv.bukkit;
|
||||
|
||||
import com.discordsrv.common.dependency.InitialDependencyLoader;
|
||||
import com.discordsrv.logging.Logger;
|
||||
import com.discordsrv.logging.impl.JavaLoggerImpl;
|
||||
import com.discordsrv.common.logging.Logger;
|
||||
import com.discordsrv.common.logging.impl.JavaLoggerImpl;
|
||||
import dev.vankka.mcdependencydownload.bukkit.bootstrap.BukkitBootstrap;
|
||||
import dev.vankka.mcdependencydownload.classloader.JarInJarClassLoader;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2021 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.bukkit.component.util;
|
||||
|
||||
import com.discordsrv.api.component.MinecraftComponent;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.component.util.ComponentUtil;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitComponentSerializer;
|
||||
import org.bukkit.event.Event;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.Function;
|
||||
|
||||
public final class PaperComponentUtil {
|
||||
|
||||
public static final boolean IS_PAPER_ADVENTURE;
|
||||
|
||||
static {
|
||||
boolean isPaperAdventure = false;
|
||||
try {
|
||||
Class.forName("io.papermc.paper.event.player.AsyncChatEvent");
|
||||
isPaperAdventure = true;
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
IS_PAPER_ADVENTURE = isPaperAdventure;
|
||||
}
|
||||
|
||||
private PaperComponentUtil() {}
|
||||
|
||||
public static <T extends Event> MinecraftComponent getComponent(
|
||||
DiscordSRV discordSRV, T source, String methodName, Function<T, String> legacy) {
|
||||
if (!IS_PAPER_ADVENTURE) {
|
||||
return getLegacy(legacy.apply(source));
|
||||
}
|
||||
|
||||
return getComponent(discordSRV, source, methodName);
|
||||
}
|
||||
|
||||
private static MinecraftComponent getLegacy(String legacy) {
|
||||
return ComponentUtil.toAPI(BukkitComponentSerializer.legacy().deserialize(legacy));
|
||||
}
|
||||
|
||||
public static MinecraftComponent getComponent(DiscordSRV discordSRV, Object source, String methodName) {
|
||||
if (!IS_PAPER_ADVENTURE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Class<?> eventClass = source.getClass();
|
||||
Object unrelocated;
|
||||
try {
|
||||
Method method = eventClass.getMethod(methodName);
|
||||
unrelocated = method.invoke(source);
|
||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
throw new IllegalStateException("Failed to invoke method reflectively", e);
|
||||
}
|
||||
|
||||
MinecraftComponent component = discordSRV.componentFactory().empty();
|
||||
MinecraftComponent.Adapter adapter = component.unrelocatedAdapter().orElse(null);
|
||||
if (adapter == null) {
|
||||
throw new IllegalStateException("Unrelocated adventure unavailable");
|
||||
}
|
||||
|
||||
adapter.setComponent(unrelocated);
|
||||
return component;
|
||||
}
|
||||
}
|
@ -19,8 +19,17 @@
|
||||
package com.discordsrv.bukkit.config.main;
|
||||
|
||||
import com.discordsrv.common.config.main.MainConfig;
|
||||
import com.discordsrv.common.config.main.channels.base.ChannelConfig;
|
||||
import com.discordsrv.common.server.config.channels.base.ServerBaseChannelConfig;
|
||||
import com.discordsrv.common.server.config.channels.base.ServerChannelConfig;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
|
||||
@ConfigSerializable
|
||||
public class BukkitConfig extends MainConfig {
|
||||
|
||||
public BukkitConfig() {
|
||||
channels.clear();
|
||||
channels.put("global", new ServerChannelConfig());
|
||||
channels.put(ChannelConfig.DEFAULT_KEY, new ServerBaseChannelConfig());
|
||||
}
|
||||
}
|
||||
|
@ -20,9 +20,9 @@ package com.discordsrv.bukkit.config.manager;
|
||||
|
||||
import com.discordsrv.bukkit.config.main.BukkitConfig;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.config.manager.MainConfigManager;
|
||||
import com.discordsrv.common.server.config.manager.ServerConfigManager;
|
||||
|
||||
public class BukkitConfigManager extends MainConfigManager<BukkitConfig> {
|
||||
public class BukkitConfigManager extends ServerConfigManager<BukkitConfig> {
|
||||
|
||||
public BukkitConfigManager(DiscordSRV discordSRV) {
|
||||
super(discordSRV);
|
||||
|
@ -20,9 +20,9 @@ package com.discordsrv.bukkit.console;
|
||||
|
||||
import com.discordsrv.bukkit.BukkitDiscordSRV;
|
||||
import com.discordsrv.common.console.Console;
|
||||
import com.discordsrv.logging.backend.LoggingBackend;
|
||||
import com.discordsrv.logging.impl.JavaLoggerImpl;
|
||||
import com.discordsrv.logging.impl.Log4JLoggerImpl;
|
||||
import com.discordsrv.common.logging.backend.LoggingBackend;
|
||||
import com.discordsrv.common.logging.impl.JavaLoggerImpl;
|
||||
import com.discordsrv.common.logging.impl.Log4JLoggerImpl;
|
||||
import net.kyori.adventure.identity.Identity;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -19,8 +19,9 @@
|
||||
package com.discordsrv.bukkit.listener;
|
||||
|
||||
import com.discordsrv.api.component.MinecraftComponent;
|
||||
import com.discordsrv.api.event.events.message.receive.game.ChatMessageProcessingEvent;
|
||||
import com.discordsrv.api.event.events.message.receive.game.GameChatMessageReceiveEvent;
|
||||
import com.discordsrv.bukkit.BukkitDiscordSRV;
|
||||
import com.discordsrv.bukkit.component.util.PaperComponentUtil;
|
||||
import com.discordsrv.common.channel.DefaultGlobalChannel;
|
||||
import com.discordsrv.common.component.util.ComponentUtil;
|
||||
import io.papermc.paper.event.player.AsyncChatEvent;
|
||||
@ -30,20 +31,13 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public abstract class BukkitChatListener implements Listener {
|
||||
|
||||
public static BukkitChatListener get(BukkitDiscordSRV discordSRV) {
|
||||
|
||||
// TODO: config option
|
||||
//noinspection ConstantConditions
|
||||
if (1 == 2) {
|
||||
try {
|
||||
Class.forName("io.papermc.paper.event.player.AsyncChatEvent");
|
||||
return new Paper(discordSRV);
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
//noinspection ConstantConditions,PointlessBooleanExpression
|
||||
if (1 == 2 && PaperComponentUtil.IS_PAPER_ADVENTURE) {
|
||||
return new Paper(discordSRV);
|
||||
}
|
||||
|
||||
return new Bukkit(discordSRV);
|
||||
@ -56,14 +50,14 @@ public abstract class BukkitChatListener implements Listener {
|
||||
}
|
||||
|
||||
protected void publishEvent(Player player, MinecraftComponent component, boolean cancelled) {
|
||||
discordSRV.eventBus().publish(
|
||||
new ChatMessageProcessingEvent(
|
||||
discordSRV.scheduler().run(() -> discordSRV.eventBus().publish(
|
||||
new GameChatMessageReceiveEvent(
|
||||
discordSRV.playerProvider().player(player),
|
||||
component,
|
||||
new DefaultGlobalChannel(discordSRV),
|
||||
component,
|
||||
cancelled
|
||||
)
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
static class Bukkit extends BukkitChatListener {
|
||||
@ -84,39 +78,13 @@ public abstract class BukkitChatListener implements Listener {
|
||||
|
||||
static class Paper extends BukkitChatListener {
|
||||
|
||||
private static final Method MESSAGE_METHOD;
|
||||
|
||||
static {
|
||||
try {
|
||||
MESSAGE_METHOD = AsyncChatEvent.class.getMethod("message");
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Paper(BukkitDiscordSRV discordSRV) {
|
||||
super(discordSRV);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onAsyncChat(AsyncChatEvent event) {
|
||||
MinecraftComponent component = discordSRV.componentFactory().empty();
|
||||
|
||||
Object unrelocated;
|
||||
try {
|
||||
unrelocated = MESSAGE_METHOD.invoke(event);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
discordSRV.logger().error("Failed to get message from Paper AsyncChatEvent", e);
|
||||
return;
|
||||
}
|
||||
|
||||
MinecraftComponent.Adapter adapter = component.unrelocatedAdapter().orElse(null);
|
||||
if (adapter == null) {
|
||||
discordSRV.logger().error("Failed to get unrelocated adventure adapter for Paper AsyncChatEvent listener");
|
||||
return;
|
||||
}
|
||||
|
||||
adapter.setComponent(unrelocated);
|
||||
MinecraftComponent component = PaperComponentUtil.getComponent(discordSRV, event, "message");
|
||||
publishEvent(
|
||||
event.getPlayer(),
|
||||
component,
|
||||
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2021 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.bukkit.listener;
|
||||
|
||||
import com.discordsrv.api.component.MinecraftComponent;
|
||||
import com.discordsrv.api.event.events.message.receive.game.DeathMessageReceiveEvent;
|
||||
import com.discordsrv.api.player.DiscordSRVPlayer;
|
||||
import com.discordsrv.bukkit.BukkitDiscordSRV;
|
||||
import com.discordsrv.bukkit.component.util.PaperComponentUtil;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
|
||||
public class BukkitDeathListener implements Listener {
|
||||
|
||||
private final BukkitDiscordSRV discordSRV;
|
||||
|
||||
public BukkitDeathListener(BukkitDiscordSRV discordSRV) {
|
||||
this.discordSRV = discordSRV;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // Paper
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerDeath(PlayerDeathEvent event) {
|
||||
DiscordSRVPlayer player = discordSRV.playerProvider().player(event.getEntity());
|
||||
MinecraftComponent component = PaperComponentUtil.getComponent(discordSRV, event, "deathMessage", PlayerDeathEvent::getDeathMessage);
|
||||
|
||||
discordSRV.scheduler().run(() -> discordSRV.eventBus().publish(
|
||||
new DeathMessageReceiveEvent(player, null, component, event.isCancelled())));
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2021 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.bukkit.listener;
|
||||
|
||||
import com.discordsrv.api.component.MinecraftComponent;
|
||||
import com.discordsrv.api.event.events.message.receive.game.JoinMessageReceiveEvent;
|
||||
import com.discordsrv.api.event.events.message.receive.game.LeaveMessageReceiveEvent;
|
||||
import com.discordsrv.api.player.DiscordSRVPlayer;
|
||||
import com.discordsrv.bukkit.BukkitDiscordSRV;
|
||||
import com.discordsrv.bukkit.component.util.PaperComponentUtil;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
public class BukkitStatusMessageListener implements Listener {
|
||||
|
||||
private final BukkitDiscordSRV discordSRV;
|
||||
|
||||
public BukkitStatusMessageListener(BukkitDiscordSRV discordSRV) {
|
||||
this.discordSRV = discordSRV;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // Paper
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
DiscordSRVPlayer player = discordSRV.playerProvider().player(event.getPlayer());
|
||||
MinecraftComponent component = PaperComponentUtil.getComponent(
|
||||
discordSRV, event, "joinMessage", PlayerJoinEvent::getJoinMessage);
|
||||
|
||||
discordSRV.scheduler().run(() -> discordSRV.eventBus().publish(
|
||||
new JoinMessageReceiveEvent(player, null, component, false)
|
||||
));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // Paper
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
DiscordSRVPlayer player = discordSRV.playerProvider().player(event.getPlayer());
|
||||
MinecraftComponent component = PaperComponentUtil.getComponent(
|
||||
discordSRV, event, "quitMessage", PlayerQuitEvent::getQuitMessage);
|
||||
|
||||
discordSRV.scheduler().run(() -> discordSRV.eventBus().publish(
|
||||
new LeaveMessageReceiveEvent(player, null, component, false)
|
||||
));
|
||||
}
|
||||
}
|
@ -38,7 +38,7 @@ public class BukkitOfflinePlayer implements IOfflinePlayer {
|
||||
|
||||
@SuppressWarnings("NullabilityProblems")
|
||||
@Override
|
||||
public String getUsername() {
|
||||
public String username() {
|
||||
return offlinePlayer.getName();
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ public class BukkitPlayer extends BukkitOfflinePlayer implements IPlayer {
|
||||
|
||||
@SuppressWarnings("deprecation") // Paper
|
||||
@Override
|
||||
public @NotNull Component getDisplayName() {
|
||||
public @NotNull Component displayName() {
|
||||
if (DISPLAY_NAME_METHOD != null) {
|
||||
try {
|
||||
return ComponentUtil.fromUnrelocated(DISPLAY_NAME_METHOD.invoke(player));
|
||||
|
@ -24,8 +24,8 @@ import com.discordsrv.common.config.connection.ConnectionConfig;
|
||||
import com.discordsrv.common.config.main.MainConfig;
|
||||
import com.discordsrv.common.config.manager.ConnectionConfigManager;
|
||||
import com.discordsrv.common.config.manager.MainConfigManager;
|
||||
import com.discordsrv.logging.Logger;
|
||||
import com.discordsrv.common.proxy.ProxyDiscordSRV;
|
||||
import com.discordsrv.common.logging.Logger;
|
||||
import com.discordsrv.proxy.ProxyDiscordSRV;
|
||||
import com.discordsrv.common.scheduler.StandardScheduler;
|
||||
import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
|
@ -19,8 +19,8 @@
|
||||
package com.discordsrv.bungee;
|
||||
|
||||
import com.discordsrv.common.dependency.InitialDependencyLoader;
|
||||
import com.discordsrv.logging.Logger;
|
||||
import com.discordsrv.logging.impl.JavaLoggerImpl;
|
||||
import com.discordsrv.common.logging.Logger;
|
||||
import com.discordsrv.common.logging.impl.JavaLoggerImpl;
|
||||
import dev.vankka.mcdependencydownload.bungee.bootstrap.BungeeBootstrap;
|
||||
import dev.vankka.mcdependencydownload.classloader.JarInJarClassLoader;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
|
@ -20,8 +20,8 @@ package com.discordsrv.bungee.console;
|
||||
|
||||
import com.discordsrv.bungee.BungeeDiscordSRV;
|
||||
import com.discordsrv.common.console.Console;
|
||||
import com.discordsrv.logging.backend.LoggingBackend;
|
||||
import com.discordsrv.logging.impl.JavaLoggerImpl;
|
||||
import com.discordsrv.common.logging.backend.LoggingBackend;
|
||||
import com.discordsrv.common.logging.impl.JavaLoggerImpl;
|
||||
import net.kyori.adventure.identity.Identity;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -65,7 +65,7 @@ public class BungeePlayer implements IPlayer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getUsername() {
|
||||
public @NotNull String username() {
|
||||
return player.getName();
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ public class BungeePlayer implements IPlayer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Component getDisplayName() {
|
||||
public @NotNull Component displayName() {
|
||||
return BungeeComponentUtil.fromLegacy(player.getDisplayName());
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,5 @@ dependencies {
|
||||
api project(':api')
|
||||
|
||||
// Logging
|
||||
api 'org.slf4j:slf4j-api:1.6.99'
|
||||
compileOnly 'org.apache.logging.log4j:log4j-core:2.0-beta9'
|
||||
api 'org.slf4j:slf4j-api:1.7.32'
|
||||
}
|
||||
|
@ -16,9 +16,8 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.logging.backend;
|
||||
package com.discordsrv.common.logging;
|
||||
|
||||
import com.discordsrv.logging.LogLevel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
@ -16,7 +16,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.logging;
|
||||
package com.discordsrv.common.logging;
|
||||
|
||||
public interface LogLevel {
|
||||
|
@ -16,10 +16,10 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.logging.adapter;
|
||||
package com.discordsrv.common.logging.adapter;
|
||||
|
||||
import com.discordsrv.logging.LogLevel;
|
||||
import com.discordsrv.logging.backend.LogAppender;
|
||||
import com.discordsrv.common.logging.LogAppender;
|
||||
import com.discordsrv.common.logging.LogLevel;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.helpers.MarkerIgnoringBase;
|
||||
import org.slf4j.spi.LocationAwareLogger;
|
@ -18,11 +18,10 @@
|
||||
|
||||
package org.slf4j.impl;
|
||||
|
||||
import com.discordsrv.logging.adapter.DependencyLoggerAdapter;
|
||||
import com.discordsrv.common.logging.adapter.DependencyLoggerAdapter;
|
||||
import org.slf4j.ILoggerFactory;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
@ -32,6 +31,6 @@ public class DiscordSRVLoggerFactory implements ILoggerFactory {
|
||||
|
||||
@Override
|
||||
public Logger getLogger(String s) {
|
||||
return loggerMap.computeIfAbsent(s.toLowerCase(Locale.ROOT), DependencyLoggerAdapter::new);
|
||||
return loggerMap.computeIfAbsent(s, DependencyLoggerAdapter::new);
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,10 @@ dependencies {
|
||||
runtimeDownloadApi 'org.spongepowered:configurate-yaml:' + rootProject.configurateVersion
|
||||
runtimeDownloadApi 'org.spongepowered:configurate-hocon:' + rootProject.configurateVersion
|
||||
|
||||
// Logging
|
||||
compileOnlyApi project(':common:common-slf4j-hack')
|
||||
compileOnly 'org.apache.logging.log4j:log4j-core:2.0-beta9'
|
||||
|
||||
// Adventure, MCDiscordReserializer, EnhancedLegacyText
|
||||
runtimeDownloadApi 'net.kyori:adventure-api:' + rootProject.adventureVersion
|
||||
runtimeDownloadApi 'net.kyori:adventure-text-serializer-plain:' + rootProject.adventureVersion
|
||||
@ -51,6 +55,9 @@ dependencies {
|
||||
// Database Drivers
|
||||
h2Driver 'com.h2database:h2:1.4.200'
|
||||
mysqlDriver 'mysql:mysql-connector-java:8.0.25'
|
||||
|
||||
// Integrations
|
||||
compileOnlyApi 'net.luckperms:api:5.3'
|
||||
}
|
||||
|
||||
processResources {
|
||||
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2021 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.proxy;
|
||||
|
||||
import com.discordsrv.common.AbstractDiscordSRV;
|
||||
import com.discordsrv.common.config.connection.ConnectionConfig;
|
||||
import com.discordsrv.common.config.main.MainConfig;
|
||||
import com.discordsrv.common.module.ModuleInitializationFunction;
|
||||
import com.discordsrv.proxy.modules.ServerSwitchMessageModule;
|
||||
|
||||
public abstract class ProxyDiscordSRV<C extends MainConfig, CC extends ConnectionConfig> extends AbstractDiscordSRV<C, CC> {
|
||||
|
||||
@Override
|
||||
protected void enable() throws Throwable {
|
||||
super.enable();
|
||||
|
||||
for (ModuleInitializationFunction function : new ModuleInitializationFunction[]{
|
||||
ServerSwitchMessageModule::new
|
||||
}) {
|
||||
try {
|
||||
registerModule(function.initialize(this));
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.discordsrv.proxy.config.channels;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.message.DiscordMessageEmbed;
|
||||
import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage;
|
||||
import com.discordsrv.common.config.annotation.Untranslated;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
|
||||
@ConfigSerializable
|
||||
public class ServerSwitchMessageConfig {
|
||||
|
||||
public boolean enabled = true;
|
||||
|
||||
@Untranslated(Untranslated.Type.VALUE)
|
||||
public SendableDiscordMessage.Builder format = SendableDiscordMessage.builder()
|
||||
.addEmbed(
|
||||
DiscordMessageEmbed.builder()
|
||||
.setAuthor(
|
||||
"%player_display_name% switched from %from_server% to %to_server%",
|
||||
null,
|
||||
"%player_avatar_url%"
|
||||
)
|
||||
.setColor(0x5555FF)
|
||||
.build()
|
||||
);
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2021 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.proxy.config.channels.base;
|
||||
|
||||
import com.discordsrv.common.config.annotation.Order;
|
||||
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
|
||||
import com.discordsrv.proxy.config.channels.ServerSwitchMessageConfig;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
|
||||
@ConfigSerializable
|
||||
public class ProxyBaseChannelConfig extends BaseChannelConfig {
|
||||
|
||||
@Order(1)
|
||||
public ServerSwitchMessageConfig serverSwitchMessages = new ServerSwitchMessageConfig();
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package com.discordsrv.proxy.config.channels.base;
|
||||
|
||||
import com.discordsrv.common.config.main.channels.base.IChannelConfig;
|
||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ProxyChannelConfig extends ProxyBaseChannelConfig implements IChannelConfig {
|
||||
|
||||
public ProxyChannelConfig() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
@Comment(CHANNEL_IDS_COMMENT)
|
||||
public List<Long> channelIds = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public List<Long> ids() {
|
||||
return channelIds;
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package com.discordsrv.proxy.config.manager;
|
||||
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.config.main.MainConfig;
|
||||
import com.discordsrv.common.config.main.channels.base.ChannelConfig;
|
||||
import com.discordsrv.common.config.manager.MainConfigManager;
|
||||
import com.discordsrv.proxy.config.channels.base.ProxyBaseChannelConfig;
|
||||
import com.discordsrv.proxy.config.channels.base.ProxyChannelConfig;
|
||||
import org.spongepowered.configurate.objectmapping.ObjectMapper;
|
||||
|
||||
public abstract class ProxyConfigManager<T extends MainConfig> extends MainConfigManager<T> {
|
||||
|
||||
public ProxyConfigManager(DiscordSRV discordSRV) {
|
||||
super(discordSRV);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelConfig.Serializer getChannelConfigSerializer(ObjectMapper.Factory mapperFactory) {
|
||||
return new ChannelConfig.Serializer(mapperFactory, ProxyBaseChannelConfig.class, ProxyChannelConfig.class);
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
package com.discordsrv.proxy.config;
|
@ -0,0 +1,51 @@
|
||||
package com.discordsrv.proxy.modules;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster;
|
||||
import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage;
|
||||
import com.discordsrv.api.event.bus.EventPriority;
|
||||
import com.discordsrv.api.event.bus.Subscribe;
|
||||
import com.discordsrv.api.event.events.message.forward.game.ServerSwitchMessageForwardedEvent;
|
||||
import com.discordsrv.api.event.events.message.receive.game.ServerSwitchMessageReceiveEvent;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
|
||||
import com.discordsrv.common.function.OrDefault;
|
||||
import com.discordsrv.common.module.modules.message.AbstractGameMessageModule;
|
||||
import com.discordsrv.proxy.config.channels.ServerSwitchMessageConfig;
|
||||
import com.discordsrv.proxy.config.channels.base.ProxyBaseChannelConfig;
|
||||
|
||||
public class ServerSwitchMessageModule extends AbstractGameMessageModule<ServerSwitchMessageConfig> {
|
||||
|
||||
public ServerSwitchMessageModule(DiscordSRV discordSRV) {
|
||||
super(discordSRV);
|
||||
}
|
||||
|
||||
@Subscribe(priority = EventPriority.LAST)
|
||||
public void onServerSwitchReceive(ServerSwitchMessageReceiveEvent event) {
|
||||
if (checkCancellation(event) || checkProcessor(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
process(event, event.getPlayer(), null);
|
||||
event.markAsProcessed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrDefault<ServerSwitchMessageConfig> mapConfig(OrDefault<BaseChannelConfig> channelConfig) {
|
||||
return channelConfig.map(cfg -> ((ProxyBaseChannelConfig) cfg).serverSwitchMessages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(OrDefault<ServerSwitchMessageConfig> config) {
|
||||
return config.get(cfg -> cfg.enabled, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SendableDiscordMessage.Builder getFormat(OrDefault<ServerSwitchMessageConfig> config) {
|
||||
return config.get(cfg -> cfg.format);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postClusterToEventBus(ReceivedDiscordMessageCluster cluster) {
|
||||
discordSRV.eventBus().publish(new ServerSwitchMessageForwardedEvent(cluster));
|
||||
}
|
||||
}
|
@ -21,6 +21,8 @@ package com.discordsrv.common.server;
|
||||
import com.discordsrv.common.AbstractDiscordSRV;
|
||||
import com.discordsrv.common.config.connection.ConnectionConfig;
|
||||
import com.discordsrv.common.config.main.MainConfig;
|
||||
import com.discordsrv.common.module.ModuleInitializationFunction;
|
||||
import com.discordsrv.common.server.modules.DeathMessageModule;
|
||||
import com.discordsrv.common.server.player.ServerPlayerProvider;
|
||||
import com.discordsrv.common.server.scheduler.ServerScheduler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -36,6 +38,19 @@ public abstract class ServerDiscordSRV<C extends MainConfig, CC extends Connecti
|
||||
@Override
|
||||
public abstract @NotNull ServerPlayerProvider<?> playerProvider();
|
||||
|
||||
@Override
|
||||
protected void enable() throws Throwable {
|
||||
super.enable();
|
||||
|
||||
for (ModuleInitializationFunction function : new ModuleInitializationFunction[]{
|
||||
DeathMessageModule::new
|
||||
}) {
|
||||
try {
|
||||
registerModule(function.initialize(this));
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
public final CompletableFuture<Void> invokeServerStarted() {
|
||||
return invokeLifecycle(this::serverStarted, "Failed to enable", true);
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2021 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.server.config.channels;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.message.DiscordMessageEmbed;
|
||||
import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage;
|
||||
import com.discordsrv.common.config.annotation.Untranslated;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||
|
||||
@ConfigSerializable
|
||||
public class DeathMessageConfig {
|
||||
|
||||
@Comment("Enable death message forwarding")
|
||||
public boolean enabled = true;
|
||||
|
||||
@Untranslated(Untranslated.Type.VALUE)
|
||||
public SendableDiscordMessage.Builder format = SendableDiscordMessage.builder()
|
||||
.addEmbed(
|
||||
DiscordMessageEmbed.builder()
|
||||
.setAuthor("%message%", null, "%player_avatar_url%")
|
||||
.setColor(1)
|
||||
.build()
|
||||
);
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2021 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.server.config.channels.base;
|
||||
|
||||
import com.discordsrv.common.config.annotation.Order;
|
||||
import com.discordsrv.common.server.config.channels.DeathMessageConfig;
|
||||
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
|
||||
@ConfigSerializable
|
||||
public class ServerBaseChannelConfig extends BaseChannelConfig {
|
||||
|
||||
@Order(1)
|
||||
public DeathMessageConfig deathMessages = new DeathMessageConfig();
|
||||
}
|
@ -16,39 +16,27 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.common.config.main.channels;
|
||||
package com.discordsrv.common.server.config.channels.base;
|
||||
|
||||
import com.discordsrv.common.config.main.channels.base.IChannelConfig;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ConfigSerializable
|
||||
public class ChannelConfig extends BaseChannelConfig {
|
||||
public class ServerChannelConfig extends ServerBaseChannelConfig implements IChannelConfig {
|
||||
|
||||
public static final String DEFAULT_KEY = "default";
|
||||
|
||||
public ChannelConfig() {
|
||||
// Clear everything besides channelIds by default (these will be filled back in by Configurate if they are in the config itself)
|
||||
for (Field field : getClass().getFields()) {
|
||||
int modifiers = field.getModifiers();
|
||||
if (!Modifier.isPublic(modifiers) || Modifier.isFinal(modifiers) || Modifier.isStatic(modifiers)) {
|
||||
continue;
|
||||
}
|
||||
if (field.getName().equals("channelIds")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
field.set(this, null);
|
||||
} catch (IllegalAccessException ignored) {}
|
||||
}
|
||||
public ServerChannelConfig() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
@Comment("The channels this in-game channel will forward to in Discord")
|
||||
@Comment(CHANNEL_IDS_COMMENT)
|
||||
public List<Long> channelIds = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public List<Long> ids() {
|
||||
return channelIds;
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2021 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.server.config.manager;
|
||||
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.config.main.MainConfig;
|
||||
import com.discordsrv.common.config.main.channels.base.ChannelConfig;
|
||||
import com.discordsrv.common.config.manager.MainConfigManager;
|
||||
import com.discordsrv.common.server.config.channels.base.ServerBaseChannelConfig;
|
||||
import com.discordsrv.common.server.config.channels.base.ServerChannelConfig;
|
||||
import org.spongepowered.configurate.objectmapping.ObjectMapper;
|
||||
|
||||
public abstract class ServerConfigManager<T extends MainConfig> extends MainConfigManager<T> {
|
||||
|
||||
public ServerConfigManager(DiscordSRV discordSRV) {
|
||||
super(discordSRV);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelConfig.Serializer getChannelConfigSerializer(ObjectMapper.Factory mapperFactory) {
|
||||
return new ChannelConfig.Serializer(mapperFactory, ServerBaseChannelConfig.class, ServerChannelConfig.class);
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2021 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.server.modules;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster;
|
||||
import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage;
|
||||
import com.discordsrv.api.event.bus.EventPriority;
|
||||
import com.discordsrv.api.event.bus.Subscribe;
|
||||
import com.discordsrv.api.event.events.message.forward.game.DeathMessageForwardedEvent;
|
||||
import com.discordsrv.api.event.events.message.receive.game.DeathMessageReceiveEvent;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
|
||||
import com.discordsrv.common.server.config.channels.DeathMessageConfig;
|
||||
import com.discordsrv.common.function.OrDefault;
|
||||
import com.discordsrv.common.module.modules.message.AbstractGameMessageModule;
|
||||
import com.discordsrv.common.server.config.channels.base.ServerBaseChannelConfig;
|
||||
|
||||
public class DeathMessageModule extends AbstractGameMessageModule<DeathMessageConfig> {
|
||||
|
||||
public DeathMessageModule(DiscordSRV discordSRV) {
|
||||
super(discordSRV);
|
||||
}
|
||||
|
||||
@Subscribe(priority = EventPriority.LAST)
|
||||
public void onDeathReceive(DeathMessageReceiveEvent event) {
|
||||
if (checkCancellation(event) || checkProcessor(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
process(event, event.getPlayer(), event.getGameChannel());
|
||||
event.markAsProcessed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrDefault<DeathMessageConfig> mapConfig(OrDefault<BaseChannelConfig> channelConfig) {
|
||||
return channelConfig.map(cfg -> ((ServerBaseChannelConfig) cfg).deathMessages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(OrDefault<DeathMessageConfig> config) {
|
||||
return config.get(cfg -> cfg.enabled, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SendableDiscordMessage.Builder getFormat(OrDefault<DeathMessageConfig> config) {
|
||||
return config.get(cfg -> cfg.format);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postClusterToEventBus(ReceivedDiscordMessageCluster cluster) {
|
||||
discordSRV.eventBus().publish(new DeathMessageForwardedEvent(cluster));
|
||||
}
|
||||
}
|
3
common/slf4j-hack/build.gradle
Normal file
3
common/slf4j-hack/build.gradle
Normal file
@ -0,0 +1,3 @@
|
||||
dependencies {
|
||||
api 'org.slf4j:slf4j-api:1.7.32'
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2021 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.x.slf4j;
|
||||
|
||||
/**
|
||||
* A fake org.slf4j.Logger that is compileOnly scoped and relocated back to the real org.slf4j package.
|
||||
* This is required as we want to relocate 'org.slf4j'
|
||||
* but we also need the non-relocated version for Velocity's logging.
|
||||
*
|
||||
* Could be fixed by https://github.com/johnrengelman/shadow/issues/727
|
||||
*/
|
||||
public interface Logger extends org.slf4j.Logger {}
|
@ -35,22 +35,26 @@ import com.discordsrv.common.discord.connection.jda.JDAConnectionManager;
|
||||
import com.discordsrv.common.discord.details.DiscordConnectionDetailsImpl;
|
||||
import com.discordsrv.common.event.bus.EventBusImpl;
|
||||
import com.discordsrv.common.function.CheckedRunnable;
|
||||
import com.discordsrv.common.logging.DependencyLoggingHandler;
|
||||
import com.discordsrv.common.module.Module;
|
||||
import com.discordsrv.common.logging.dependency.DependencyLoggingHandler;
|
||||
import com.discordsrv.common.module.modules.message.JoinMessageModule;
|
||||
import com.discordsrv.common.module.modules.message.LeaveMessageModule;
|
||||
import com.discordsrv.common.module.type.AbstractModule;
|
||||
import com.discordsrv.common.module.type.Module;
|
||||
import com.discordsrv.common.module.ModuleInitializationFunction;
|
||||
import com.discordsrv.common.module.ModuleManager;
|
||||
import com.discordsrv.common.module.modules.DiscordAPIEventModule;
|
||||
import com.discordsrv.common.module.modules.DiscordToMinecraftModule;
|
||||
import com.discordsrv.common.module.modules.message.DiscordToMinecraftChatModule;
|
||||
import com.discordsrv.common.module.modules.GlobalChannelLookupModule;
|
||||
import com.discordsrv.common.module.modules.MinecraftToDiscordModule;
|
||||
import com.discordsrv.common.module.modules.message.MinecraftToDiscordChatModule;
|
||||
import com.discordsrv.common.module.modules.integration.LuckPermsIntegration;
|
||||
import com.discordsrv.common.placeholder.ComponentResultStringifier;
|
||||
import com.discordsrv.common.placeholder.PlaceholderServiceImpl;
|
||||
import com.discordsrv.common.placeholder.context.GlobalTextHandlingContext;
|
||||
import com.discordsrv.logging.adapter.DependencyLoggerAdapter;
|
||||
import com.discordsrv.common.logging.adapter.DependencyLoggerAdapter;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.OverridingMethodsMustInvokeSuper;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@ -167,12 +171,12 @@ public abstract class AbstractDiscordSRV<C extends MainConfig, CC extends Connec
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerModule(Module module) {
|
||||
public void registerModule(AbstractModule module) {
|
||||
moduleManager.register(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterModule(Module module) {
|
||||
public void unregisterModule(AbstractModule module) {
|
||||
moduleManager.unregister(module);
|
||||
}
|
||||
|
||||
@ -264,13 +268,19 @@ public abstract class AbstractDiscordSRV<C extends MainConfig, CC extends Connec
|
||||
|
||||
// Register modules
|
||||
moduleManager = new ModuleManager(this);
|
||||
for (Module module : Arrays.asList(
|
||||
new DiscordAPIEventModule(this),
|
||||
new DiscordToMinecraftModule(this),
|
||||
new GlobalChannelLookupModule(this),
|
||||
new MinecraftToDiscordModule(this)
|
||||
)) {
|
||||
registerModule(module);
|
||||
for (ModuleInitializationFunction function : new ModuleInitializationFunction[]{
|
||||
LuckPermsIntegration::new,
|
||||
|
||||
DiscordToMinecraftChatModule::new,
|
||||
JoinMessageModule::new,
|
||||
LeaveMessageModule::new,
|
||||
MinecraftToDiscordChatModule::new,
|
||||
DiscordAPIEventModule::new,
|
||||
GlobalChannelLookupModule::new
|
||||
}) {
|
||||
try {
|
||||
registerModule(function.initialize(this));
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,11 +28,12 @@ import com.discordsrv.common.config.manager.MainConfigManager;
|
||||
import com.discordsrv.common.console.Console;
|
||||
import com.discordsrv.common.discord.api.DiscordAPIImpl;
|
||||
import com.discordsrv.common.discord.connection.DiscordConnectionManager;
|
||||
import com.discordsrv.common.module.Module;
|
||||
import com.discordsrv.common.module.type.AbstractModule;
|
||||
import com.discordsrv.common.module.type.Module;
|
||||
import com.discordsrv.common.placeholder.PlaceholderServiceImpl;
|
||||
import com.discordsrv.common.player.provider.AbstractPlayerProvider;
|
||||
import com.discordsrv.common.scheduler.Scheduler;
|
||||
import com.discordsrv.logging.Logger;
|
||||
import com.discordsrv.common.logging.Logger;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -80,8 +81,8 @@ public interface DiscordSRV extends DiscordSRVApi {
|
||||
|
||||
// Modules
|
||||
<T extends Module> T getModule(Class<T> moduleType);
|
||||
void registerModule(Module module);
|
||||
void unregisterModule(Module module);
|
||||
void registerModule(AbstractModule module);
|
||||
void unregisterModule(AbstractModule module);
|
||||
|
||||
Locale locale();
|
||||
void setStatus(Status status);
|
||||
|
@ -24,17 +24,16 @@ import com.discordsrv.api.event.bus.Subscribe;
|
||||
import com.discordsrv.api.event.events.channel.GameChannelLookupEvent;
|
||||
import com.discordsrv.api.event.events.lifecycle.DiscordSRVReloadEvent;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.config.main.channels.BaseChannelConfig;
|
||||
import com.discordsrv.common.config.main.channels.ChannelConfig;
|
||||
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
|
||||
import com.discordsrv.common.config.main.channels.base.ChannelConfig;
|
||||
import com.discordsrv.common.config.main.channels.base.IChannelConfig;
|
||||
import com.discordsrv.common.function.OrDefault;
|
||||
import com.github.benmanes.caffeine.cache.CacheLoader;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -42,7 +41,7 @@ public class ChannelConfigHelper {
|
||||
|
||||
private final DiscordSRV discordSRV;
|
||||
private final LoadingCache<String, GameChannel> nameToChannelCache;
|
||||
private final Map<Long, Pair<String, ChannelConfig>> discordToConfigMap;
|
||||
private final Map<Long, Map<String, BaseChannelConfig>> discordToConfigMap;
|
||||
|
||||
public ChannelConfigHelper(DiscordSRV discordSRV) {
|
||||
this.discordSRV = discordSRV;
|
||||
@ -74,14 +73,15 @@ public class ChannelConfigHelper {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<Long, Pair<String, ChannelConfig>> newMap = new HashMap<>();
|
||||
Map<Long, Map<String, BaseChannelConfig>> newMap = new HashMap<>();
|
||||
for (Map.Entry<String, BaseChannelConfig> entry : channels().entrySet()) {
|
||||
String channelName = entry.getKey();
|
||||
BaseChannelConfig value = entry.getValue();
|
||||
if (value instanceof ChannelConfig) {
|
||||
ChannelConfig channelConfig = (ChannelConfig) value;
|
||||
for (long channelId : channelConfig.channelIds) {
|
||||
newMap.put(channelId, Pair.of(channelName, channelConfig));
|
||||
if (value instanceof IChannelConfig) {
|
||||
IChannelConfig channelConfig = (IChannelConfig) value;
|
||||
for (long channelId : channelConfig.ids()) {
|
||||
newMap.computeIfAbsent(channelId, key -> new LinkedHashMap<>())
|
||||
.put(channelName, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -96,22 +96,27 @@ public class ChannelConfigHelper {
|
||||
return discordSRV.config().channels;
|
||||
}
|
||||
|
||||
private BaseChannelConfig getDefault() {
|
||||
return channels().computeIfAbsent(ChannelConfig.DEFAULT_KEY, key -> new BaseChannelConfig());
|
||||
}
|
||||
|
||||
public Set<OrDefault<BaseChannelConfig>> getAllChannels() {
|
||||
BaseChannelConfig defaultConfig = getDefault();
|
||||
|
||||
Set<OrDefault<BaseChannelConfig>> channelConfigs = new HashSet<>();
|
||||
for (Map.Entry<String, BaseChannelConfig> entry : channels().entrySet()) {
|
||||
if (entry.getKey().equals(ChannelConfig.DEFAULT_KEY)) {
|
||||
continue;
|
||||
}
|
||||
channelConfigs.add(new OrDefault<>(entry.getValue(), defaultConfig));
|
||||
}
|
||||
return channelConfigs;
|
||||
}
|
||||
|
||||
public OrDefault<BaseChannelConfig> orDefault(GameChannel gameChannel) {
|
||||
return orDefault(gameChannel.getOwnerName(), gameChannel.getChannelName());
|
||||
}
|
||||
|
||||
public OrDefault<Pair<GameChannel, BaseChannelConfig>> orDefault(DiscordTextChannel discordTextChannel) {
|
||||
return new OrDefault<>(
|
||||
getDiscordResolved(discordTextChannel),
|
||||
Pair.of(null, getDefault())
|
||||
);
|
||||
}
|
||||
|
||||
private BaseChannelConfig getDefault() {
|
||||
return channels().computeIfAbsent(
|
||||
"default", key -> new BaseChannelConfig());
|
||||
}
|
||||
|
||||
public OrDefault<BaseChannelConfig> orDefault(String ownerName, String channelName) {
|
||||
BaseChannelConfig defaultConfig = getDefault();
|
||||
|
||||
@ -144,21 +149,39 @@ public class ChannelConfigHelper {
|
||||
return gameChannel != null ? get(gameChannel) : null;
|
||||
}
|
||||
|
||||
public Pair<GameChannel, BaseChannelConfig> getDiscordResolved(DiscordTextChannel channel) {
|
||||
Pair<String, ? extends BaseChannelConfig> pair = getDiscord(channel);
|
||||
if (pair == null) {
|
||||
return null;
|
||||
}
|
||||
public Map<GameChannel, OrDefault<BaseChannelConfig>> orDefault(DiscordTextChannel discordTextChannel) {
|
||||
BaseChannelConfig defaultConfig = getDefault();
|
||||
|
||||
GameChannel gameChannel = nameToChannelCache.get(pair.getKey());
|
||||
if (gameChannel == null) {
|
||||
return null;
|
||||
Map<GameChannel, OrDefault<BaseChannelConfig>> channels = new HashMap<>();
|
||||
for (Map.Entry<GameChannel, BaseChannelConfig> entry : getDiscordResolved(discordTextChannel).entrySet()) {
|
||||
channels.put(
|
||||
entry.getKey(),
|
||||
new OrDefault<>(entry.getValue(), defaultConfig)
|
||||
);
|
||||
}
|
||||
|
||||
return Pair.of(gameChannel, pair.getValue());
|
||||
return channels;
|
||||
}
|
||||
|
||||
public Pair<String, ? extends BaseChannelConfig> getDiscord(DiscordTextChannel channel) {
|
||||
public Map<GameChannel, BaseChannelConfig> getDiscordResolved(DiscordTextChannel channel) {
|
||||
Map<String, BaseChannelConfig> pairs = getDiscord(channel);
|
||||
if (pairs == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
Map<GameChannel, BaseChannelConfig> channels = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, BaseChannelConfig> entry : pairs.entrySet()) {
|
||||
GameChannel gameChannel = nameToChannelCache.get(entry.getKey());
|
||||
if (gameChannel == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
channels.put(gameChannel, entry.getValue());
|
||||
}
|
||||
|
||||
return channels;
|
||||
}
|
||||
|
||||
public Map<String, BaseChannelConfig> getDiscord(DiscordTextChannel channel) {
|
||||
synchronized (discordToConfigMap) {
|
||||
return discordToConfigMap.get(channel.getId());
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ import com.discordsrv.api.discord.api.entity.DiscordUser;
|
||||
import com.discordsrv.api.discord.api.entity.guild.DiscordGuild;
|
||||
import com.discordsrv.api.discord.api.entity.guild.DiscordGuildMember;
|
||||
import com.discordsrv.api.discord.api.entity.guild.DiscordRole;
|
||||
import com.discordsrv.api.event.events.message.receive.discord.DiscordMessageProcessingEvent;
|
||||
import com.discordsrv.api.event.events.message.receive.discord.DiscordChatMessageProcessingEvent;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.component.util.ComponentUtil;
|
||||
import com.discordsrv.common.config.main.channels.DiscordToMinecraftChatConfig;
|
||||
@ -47,7 +47,7 @@ public class DiscordSRVMinecraftRenderer extends DefaultMinecraftRenderer {
|
||||
}
|
||||
|
||||
public static void runInContext(
|
||||
DiscordMessageProcessingEvent event,
|
||||
DiscordChatMessageProcessingEvent event,
|
||||
OrDefault<DiscordToMinecraftChatConfig> config,
|
||||
Runnable runnable
|
||||
) {
|
||||
@ -58,7 +58,7 @@ public class DiscordSRVMinecraftRenderer extends DefaultMinecraftRenderer {
|
||||
}
|
||||
|
||||
public static <T> T getWithContext(
|
||||
DiscordMessageProcessingEvent event,
|
||||
DiscordChatMessageProcessingEvent event,
|
||||
OrDefault<DiscordToMinecraftChatConfig> config,
|
||||
Supplier<T> supplier
|
||||
) {
|
||||
@ -149,10 +149,10 @@ public class DiscordSRVMinecraftRenderer extends DefaultMinecraftRenderer {
|
||||
|
||||
private static class Context {
|
||||
|
||||
private final DiscordMessageProcessingEvent event;
|
||||
private final DiscordChatMessageProcessingEvent event;
|
||||
private final OrDefault<DiscordToMinecraftChatConfig> config;
|
||||
|
||||
public Context(DiscordMessageProcessingEvent event, OrDefault<DiscordToMinecraftChatConfig> config) {
|
||||
public Context(DiscordChatMessageProcessingEvent event, OrDefault<DiscordToMinecraftChatConfig> config) {
|
||||
this.event = event;
|
||||
this.config = config;
|
||||
}
|
||||
|
@ -22,9 +22,13 @@ import com.discordsrv.api.component.MinecraftComponent;
|
||||
import com.discordsrv.api.component.MinecraftComponentAdapter;
|
||||
import com.discordsrv.common.component.MinecraftComponentImpl;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.ComponentLike;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* An util class for {@link Component}s and {@link MinecraftComponent}s.
|
||||
*/
|
||||
@ -65,4 +69,19 @@ public final class ComponentUtil {
|
||||
.setComponent(unrelocatedAdventure);
|
||||
return fromAPI(component);
|
||||
}
|
||||
|
||||
public static Component join(Component delimiter, Collection<? extends ComponentLike> components) {
|
||||
return join(delimiter, components.toArray(new ComponentLike[0]));
|
||||
}
|
||||
|
||||
public static Component join(Component delimiter, ComponentLike[] components) {
|
||||
TextComponent.Builder builder = Component.text();
|
||||
for (int i = 0; i < components.length; i++) {
|
||||
builder.append(components[i]);
|
||||
if (i < components.length - 1) {
|
||||
builder.append(delimiter);
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2021 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.config.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Manually determines the position of the option in the config, everything is ordered {@code 0} by default,
|
||||
* and will go in the order they are defined.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface Order {
|
||||
|
||||
int value();
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2021 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.config.fielddiscoverer;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.spongepowered.configurate.objectmapping.FieldData;
|
||||
import org.spongepowered.configurate.objectmapping.FieldDiscoverer;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
import org.spongepowered.configurate.util.CheckedFunction;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class OrderedFieldDiscovererProxy<T> implements FieldDiscoverer<T> {
|
||||
|
||||
private final FieldDiscoverer<T> fieldDiscoverer;
|
||||
private final Comparator<FieldCollectorData<T, ?>> order;
|
||||
|
||||
public OrderedFieldDiscovererProxy(FieldDiscoverer<T> fieldDiscoverer, Comparator<FieldCollectorData<T, ?>> order) {
|
||||
this.fieldDiscoverer = fieldDiscoverer;
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable <V> InstanceFactory<T> discover(AnnotatedType target, FieldCollector<T, V> collector) throws SerializationException {
|
||||
List<FieldCollectorData<T, V>> data = new ArrayList<>();
|
||||
FieldCollector<T, V> fieldCollector = (name, type, annotations, deserializer, serializer) ->
|
||||
data.add(new FieldCollectorData<>(name, type, annotations, deserializer, serializer));
|
||||
|
||||
InstanceFactory<T> instanceFactory = fieldDiscoverer.discover(target, fieldCollector);
|
||||
if (instanceFactory == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
data.sort(order);
|
||||
for (FieldCollectorData<T, V> field : data) {
|
||||
collector.accept(field.name, field.type, field.annotations, field.deserializer, field.serializer);
|
||||
}
|
||||
|
||||
return instanceFactory;
|
||||
}
|
||||
|
||||
public static class FieldCollectorData<T, V> {
|
||||
|
||||
private final String name;
|
||||
private final AnnotatedType type;
|
||||
private final AnnotatedElement annotations;
|
||||
private final FieldData.Deserializer<T> deserializer;
|
||||
private final CheckedFunction<V, Object, Exception> serializer;
|
||||
|
||||
public FieldCollectorData(String name, AnnotatedType type, AnnotatedElement annotations,
|
||||
FieldData.Deserializer<T> deserializer,
|
||||
CheckedFunction<V, Object, Exception> serializer) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.annotations = annotations;
|
||||
this.deserializer = deserializer;
|
||||
this.serializer = serializer;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public AnnotatedType type() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public AnnotatedElement annotations() {
|
||||
return annotations;
|
||||
}
|
||||
}
|
||||
}
|
@ -20,12 +20,11 @@ package com.discordsrv.common.config.main;
|
||||
|
||||
import com.discordsrv.common.config.Config;
|
||||
import com.discordsrv.common.config.annotation.DefaultOnly;
|
||||
import com.discordsrv.common.config.main.channels.BaseChannelConfig;
|
||||
import com.discordsrv.common.config.main.channels.ChannelConfig;
|
||||
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
|
||||
import com.discordsrv.common.config.main.channels.base.ChannelConfig;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
@ConfigSerializable
|
||||
public class MainConfig implements Config {
|
||||
@ -40,6 +39,8 @@ public class MainConfig implements Config {
|
||||
@DefaultOnly("default")
|
||||
public Map<String, BaseChannelConfig> channels = new LinkedHashMap<String, BaseChannelConfig>() {{
|
||||
put("global", new ChannelConfig());
|
||||
put("default", new BaseChannelConfig());
|
||||
put(ChannelConfig.DEFAULT_KEY, new BaseChannelConfig());
|
||||
}};
|
||||
|
||||
public List<ChannelUpdaterConfig> channelUpdaters = new ArrayList<>(Collections.singletonList(new ChannelUpdaterConfig()));
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
package com.discordsrv.common.config.main.channels;
|
||||
|
||||
import com.discordsrv.common.config.annotation.Untranslated;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||
|
||||
@ -30,14 +31,24 @@ import java.util.regex.Pattern;
|
||||
@ConfigSerializable
|
||||
public class DiscordToMinecraftChatConfig {
|
||||
|
||||
@Comment("The Discord to Minecraft message format for regular users")
|
||||
public String format = "[ᛩF2Discord&r] [hover:show_text:Tag: %user_tag%&r\nRoles: %user_roles_, |text_&7&oNone%]%user_color%%user_effective_name%&r » %message% %message_attachments%";
|
||||
@Comment("Is Discord to Minecraft chat forwarding enabled")
|
||||
public boolean enabled = true;
|
||||
|
||||
@Comment("The Discord to Minecraft message format for regular users and bots")
|
||||
@Untranslated(Untranslated.Type.VALUE)
|
||||
public String format = "[ᛩF2Discord&r] [hover:show_text:Tag: %user_tag%&r\nRoles: %user_roles_, |text_&7&oNone%]%user_color%%user_effective_name%&r » %message%%message_attachments%";
|
||||
|
||||
@Comment("The Discord to Minecraft message format for webhook messages (if enabled)")
|
||||
public String webhookFormat = "[ᛩF2Discord&r] [hover:show_text:Webhook message]%user_name%&r » %message% %message_attachments%";
|
||||
@Untranslated(Untranslated.Type.VALUE)
|
||||
public String webhookFormat = "[ᛩF2Discord&r] [hover:show_text:Webhook message]%user_name%&r » %message%%message_attachments_ %";
|
||||
|
||||
@Comment("Attachment format")
|
||||
@Untranslated(Untranslated.Type.VALUE)
|
||||
public String attachmentFormat = "[hover:show_text:Open %file_name% in browser][click:open_url:%file_url%]&a[&f%file_name%&a]&r";
|
||||
|
||||
// TODO: more info on regex pairs (String#replaceAll)
|
||||
@Comment("Regex filters for Discord message contents (this is the %message% part of the \"format\" option)")
|
||||
@Untranslated(Untranslated.Type.VALUE)
|
||||
public Map<Pattern, String> contentRegexFilters = new LinkedHashMap<>();
|
||||
|
||||
@Comment("Users, bots and webhooks to ignore")
|
||||
@ -56,7 +67,7 @@ public class DiscordToMinecraftChatConfig {
|
||||
public boolean bots = false;
|
||||
|
||||
@Comment("If webhooks should be ignored")
|
||||
public boolean webhooks = false;
|
||||
public boolean webhooks = true;
|
||||
|
||||
@ConfigSerializable
|
||||
public static class IDs {
|
||||
@ -82,11 +93,14 @@ public class DiscordToMinecraftChatConfig {
|
||||
public static class Format {
|
||||
|
||||
@Comment("The format shown in-game")
|
||||
@Untranslated(Untranslated.Type.VALUE)
|
||||
public String format = "";
|
||||
|
||||
@Comment("The format when the entity is deleted or can't be looked up")
|
||||
@Untranslated(Untranslated.Type.VALUE)
|
||||
public String unknownFormat = "";
|
||||
|
||||
@SuppressWarnings("unused") // Configurate
|
||||
public Format() {}
|
||||
|
||||
public Format(String format, String unknownFormat) {
|
||||
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2021 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.config.main.channels;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.message.DiscordMessageEmbed;
|
||||
import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage;
|
||||
import com.discordsrv.common.config.annotation.Untranslated;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
|
||||
@ConfigSerializable
|
||||
public class JoinMessageConfig {
|
||||
|
||||
public boolean enabled = true;
|
||||
|
||||
@Untranslated(Untranslated.Type.VALUE)
|
||||
public SendableDiscordMessage.Builder format = SendableDiscordMessage.builder()
|
||||
.addEmbed(
|
||||
DiscordMessageEmbed.builder()
|
||||
.setAuthor("%player_display_name% joined", null, "%player_avatar_url%")
|
||||
.setColor(0x55FF55)
|
||||
.build()
|
||||
);
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2021 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.config.main.channels;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.message.DiscordMessageEmbed;
|
||||
import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage;
|
||||
import com.discordsrv.common.config.annotation.Untranslated;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
|
||||
@ConfigSerializable
|
||||
public class LeaveMessageConfig {
|
||||
|
||||
public boolean enabled = true;
|
||||
|
||||
@Untranslated(Untranslated.Type.VALUE)
|
||||
public SendableDiscordMessage.Builder format = SendableDiscordMessage.builder()
|
||||
.addEmbed(
|
||||
DiscordMessageEmbed.builder()
|
||||
.setAuthor("%player_display_name% left", null, "%player_avatar_url%")
|
||||
.setColor(0xFF5555)
|
||||
.build()
|
||||
);
|
||||
}
|
@ -19,6 +19,7 @@
|
||||
package com.discordsrv.common.config.main.channels;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage;
|
||||
import com.discordsrv.common.config.annotation.Untranslated;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||
|
||||
@ -29,10 +30,14 @@ import java.util.regex.Pattern;
|
||||
@ConfigSerializable
|
||||
public class MinecraftToDiscordChatConfig {
|
||||
|
||||
@Comment("Is Minecraft to Discord chat forwarding enabled")
|
||||
public boolean enabled = true;
|
||||
|
||||
@Untranslated(Untranslated.Type.VALUE)
|
||||
public SendableDiscordMessage.Builder format = SendableDiscordMessage.builder()
|
||||
.setWebhookUsername("%player_display_name%")
|
||||
.setWebhookAvatarUrl("%player_avatar_url%")
|
||||
.setContent("%message%");// TODO
|
||||
.setContent("%message%");
|
||||
|
||||
// TODO: more info on regex pairs (String#replaceAll)
|
||||
@Comment("Regex filters for Minecraft message contents (this is the %message% part of the \"format\" option)")
|
||||
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2021 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.config.main.channels.base;
|
||||
|
||||
import com.discordsrv.common.config.annotation.Order;
|
||||
import com.discordsrv.common.config.annotation.Untranslated;
|
||||
import com.discordsrv.common.config.main.channels.DiscordToMinecraftChatConfig;
|
||||
import com.discordsrv.common.config.main.channels.JoinMessageConfig;
|
||||
import com.discordsrv.common.config.main.channels.LeaveMessageConfig;
|
||||
import com.discordsrv.common.config.main.channels.MinecraftToDiscordChatConfig;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
|
||||
@ConfigSerializable
|
||||
public class BaseChannelConfig {
|
||||
|
||||
public MinecraftToDiscordChatConfig minecraftToDiscord = new MinecraftToDiscordChatConfig();
|
||||
public DiscordToMinecraftChatConfig discordToMinecraft = new DiscordToMinecraftChatConfig();
|
||||
public JoinMessageConfig joinMessages = new JoinMessageConfig();
|
||||
public LeaveMessageConfig leaveMessages = new LeaveMessageConfig();
|
||||
|
||||
@Untranslated(Untranslated.Type.VALUE)
|
||||
@Order(5)
|
||||
public String avatarUrlProvider = "https://heads.discordsrv.com/head.png?texture=%texture%&uuid=%uuid%&name=%username%&overlay";
|
||||
}
|
@ -16,38 +16,52 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.common.config.main.channels;
|
||||
package com.discordsrv.common.config.main.channels.base;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
import org.spongepowered.configurate.objectmapping.ObjectMapper;
|
||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
import org.spongepowered.configurate.serialize.TypeSerializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ConfigSerializable
|
||||
public class BaseChannelConfig {
|
||||
public class ChannelConfig extends BaseChannelConfig implements IChannelConfig {
|
||||
|
||||
public MinecraftToDiscordChatConfig minecraftToDiscord = new MinecraftToDiscordChatConfig();
|
||||
public DiscordToMinecraftChatConfig discordToMinecraft = new DiscordToMinecraftChatConfig();
|
||||
public ChannelConfig() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
public String avatarUrlProvider = "https://heads.discordsrv.com/head.png?texture=%texture%&uuid=%uuid%&name=%username%&overlay";
|
||||
@Comment(CHANNEL_IDS_COMMENT)
|
||||
public List<Long> channelIds = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public List<Long> ids() {
|
||||
return channelIds;
|
||||
}
|
||||
|
||||
public static class Serializer implements TypeSerializer<BaseChannelConfig> {
|
||||
|
||||
private final ObjectMapper.Factory mapperFactory;
|
||||
private final Class<?> baseConfigClass;
|
||||
private final Class<?> configClass;
|
||||
|
||||
public Serializer(ObjectMapper.Factory mapperFactory) {
|
||||
public Serializer(ObjectMapper.Factory mapperFactory, Class<?> baseConfigClass, Class<?> configClass) {
|
||||
this.mapperFactory = mapperFactory;
|
||||
this.baseConfigClass = baseConfigClass;
|
||||
this.configClass = configClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseChannelConfig deserialize(Type type, ConfigurationNode node) throws SerializationException {
|
||||
return (BaseChannelConfig) mapperFactory.asTypeSerializer()
|
||||
.deserialize(
|
||||
ChannelConfig.DEFAULT_KEY.equals(node.key()) ? BaseChannelConfig.class : ChannelConfig.class,
|
||||
ChannelConfig.DEFAULT_KEY.equals(node.key()) ? baseConfigClass : configClass,
|
||||
node
|
||||
);
|
||||
}
|
||||
@ -60,7 +74,7 @@ public class BaseChannelConfig {
|
||||
}
|
||||
|
||||
mapperFactory.asTypeSerializer().serialize(
|
||||
ChannelConfig.DEFAULT_KEY.equals(node.key()) ? BaseChannelConfig.class : ChannelConfig.class,
|
||||
ChannelConfig.DEFAULT_KEY.equals(node.key()) ? baseConfigClass : configClass,
|
||||
obj,
|
||||
node
|
||||
);
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2021 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.config.main.channels.base;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.List;
|
||||
|
||||
public interface IChannelConfig {
|
||||
|
||||
String DEFAULT_KEY = "default";
|
||||
String CHANNEL_IDS_COMMENT = "The channels this in-game channel will forward to in Discord";
|
||||
|
||||
default void initialize() {
|
||||
// Clear everything besides channelIds by default (these will be filled back in by Configurate if they are in the config itself)
|
||||
Class<?> clazz = getClass();
|
||||
while (clazz != null) {
|
||||
for (Field field : clazz.getFields()) {
|
||||
int modifiers = field.getModifiers();
|
||||
if (!Modifier.isPublic(modifiers) || Modifier.isFinal(modifiers) || Modifier.isStatic(modifiers)) {
|
||||
continue;
|
||||
}
|
||||
if (field.getName().equals("channelIds")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
field.set(this, null);
|
||||
} catch (IllegalAccessException ignored) {}
|
||||
}
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
}
|
||||
|
||||
List<Long> ids();
|
||||
}
|
@ -19,17 +19,12 @@
|
||||
package com.discordsrv.common.config.manager.loader;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.spongepowered.configurate.ConfigurationOptions;
|
||||
import org.spongepowered.configurate.loader.AbstractConfigurationLoader;
|
||||
import org.spongepowered.configurate.yaml.NodeStyle;
|
||||
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
|
||||
|
||||
public interface YamlConfigLoaderProvider extends ConfigLoaderProvider<YamlConfigurationLoader> {
|
||||
|
||||
default ConfigurationOptions defaultOptions() {
|
||||
return ConfigurationOptions.defaults();
|
||||
}
|
||||
|
||||
default NodeStyle nodeStyle() {
|
||||
return NodeStyle.BLOCK;
|
||||
}
|
||||
|
@ -23,7 +23,10 @@ import com.discordsrv.api.discord.api.entity.message.DiscordMessageEmbed;
|
||||
import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.config.annotation.DefaultOnly;
|
||||
import com.discordsrv.common.config.main.channels.BaseChannelConfig;
|
||||
import com.discordsrv.common.config.annotation.Order;
|
||||
import com.discordsrv.common.config.fielddiscoverer.OrderedFieldDiscovererProxy;
|
||||
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
|
||||
import com.discordsrv.common.config.main.channels.base.ChannelConfig;
|
||||
import com.discordsrv.common.config.manager.loader.ConfigLoaderProvider;
|
||||
import com.discordsrv.common.config.serializer.ColorSerializer;
|
||||
import com.discordsrv.common.config.serializer.DiscordMessageEmbedSerializer;
|
||||
@ -37,6 +40,7 @@ import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.ConfigurationOptions;
|
||||
import org.spongepowered.configurate.loader.AbstractConfigurationLoader;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
import org.spongepowered.configurate.objectmapping.FieldDiscoverer;
|
||||
import org.spongepowered.configurate.objectmapping.ObjectMapper;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
import org.spongepowered.configurate.util.NamingScheme;
|
||||
@ -44,6 +48,7 @@ import org.spongepowered.configurate.util.NamingSchemes;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
@ -88,18 +93,30 @@ public abstract class ConfigurateConfigManager<T, LT extends AbstractConfigurati
|
||||
|
||||
protected abstract String fileName();
|
||||
|
||||
public ChannelConfig.Serializer getChannelConfigSerializer( ObjectMapper.Factory mapperFactory) {
|
||||
return new ChannelConfig.Serializer(mapperFactory, BaseChannelConfig.class, ChannelConfig.class);
|
||||
}
|
||||
|
||||
public ConfigurationOptions defaultOptions() {
|
||||
return ConfigurationOptions.defaults()
|
||||
.shouldCopyDefaults(false)
|
||||
.implicitInitialization(false)
|
||||
.serializers(builder -> {
|
||||
ObjectMapper.Factory objectMapper = configObjectMapper();
|
||||
builder.register(BaseChannelConfig.class, getChannelConfigSerializer(objectMapper));
|
||||
builder.register(Color.class, new ColorSerializer());
|
||||
builder.register(Pattern.class, new PatternSerializer());
|
||||
builder.register(BaseChannelConfig.class, new BaseChannelConfig.Serializer(objectMapper));
|
||||
builder.register(DiscordMessageEmbed.Builder.class, new DiscordMessageEmbedSerializer(NAMING_SCHEME));
|
||||
builder.register(DiscordMessageEmbed.Field.class, new DiscordMessageEmbedSerializer.FieldSerializer(NAMING_SCHEME));
|
||||
builder.register(SendableDiscordMessage.Builder.class, new SendableDiscordMessageSerializer(NAMING_SCHEME));
|
||||
|
||||
// give Configurate' serializers the ObjectMapper mapper
|
||||
builder.register(type -> {
|
||||
String typeName = type.getTypeName();
|
||||
return typeName.startsWith("com.discordsrv")
|
||||
&& !typeName.startsWith("com.discordsrv.dependencies")
|
||||
&& !typeName.contains(".serializer");
|
||||
}, objectMapper.asTypeSerializer());
|
||||
});
|
||||
}
|
||||
|
||||
@ -111,12 +128,20 @@ public abstract class ConfigurateConfigManager<T, LT extends AbstractConfigurati
|
||||
return defaultOptions();
|
||||
}
|
||||
|
||||
protected ObjectMapper.Factory.Builder objectMapperBuilder() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public ObjectMapper.Factory.Builder objectMapperBuilder() {
|
||||
Comparator<OrderedFieldDiscovererProxy.FieldCollectorData<Object, ?>> fieldOrder = Comparator.comparingInt(data -> {
|
||||
Order order = data.annotations().getAnnotation(Order.class);
|
||||
return order != null ? order.value() : 0;
|
||||
});
|
||||
|
||||
return ObjectMapper.factoryBuilder()
|
||||
.defaultNamingScheme(NAMING_SCHEME);
|
||||
.defaultNamingScheme(NAMING_SCHEME)
|
||||
.addDiscoverer(new OrderedFieldDiscovererProxy<>((FieldDiscoverer<Object>) FieldDiscoverer.emptyConstructorObject(), fieldOrder))
|
||||
.addDiscoverer(new OrderedFieldDiscovererProxy<>((FieldDiscoverer<Object>) FieldDiscoverer.record(), fieldOrder));
|
||||
}
|
||||
|
||||
protected ObjectMapper.Factory.Builder configObjectMapperBuilder() {
|
||||
public ObjectMapper.Factory.Builder configObjectMapperBuilder() {
|
||||
return objectMapperBuilder();
|
||||
}
|
||||
|
||||
@ -164,9 +189,13 @@ public abstract class ConfigurateConfigManager<T, LT extends AbstractConfigurati
|
||||
}
|
||||
|
||||
private CommentedConfigurationNode getDefault(T defaultConfig, boolean cleanMapper) throws SerializationException {
|
||||
return getDefault(defaultConfig, cleanMapper ? defaultObjectMapper() : configObjectMapper());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private CommentedConfigurationNode getDefault(T defaultConfig, ObjectMapper.Factory mapperFactory) throws SerializationException {
|
||||
CommentedConfigurationNode node = CommentedConfigurationNode.root(defaultNodeOptions());
|
||||
(cleanMapper ? defaultObjectMapper() : configObjectMapper())
|
||||
.get(defaultConfig.getClass()).load(node);
|
||||
mapperFactory.get((Class<T>) defaultConfig.getClass()).save(defaultConfig, node);
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -175,6 +204,10 @@ public abstract class ConfigurateConfigManager<T, LT extends AbstractConfigurati
|
||||
return null;
|
||||
}
|
||||
|
||||
public CommentedConfigurationNode getDefaultNode(ObjectMapper.Factory mapperFactory) throws ConfigurateException {
|
||||
return getDefault(createConfiguration(), mapperFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() throws ConfigException {
|
||||
reload();
|
||||
|
@ -30,6 +30,9 @@ import org.spongepowered.configurate.serialize.SerializationException;
|
||||
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class TranslatedConfigManager<T extends Config, LT extends AbstractConfigurationLoader<CommentedConfigurationNode>>
|
||||
extends ConfigurateConfigManager<T, LT> {
|
||||
@ -64,17 +67,18 @@ public abstract class TranslatedConfigManager<T extends Config, LT extends Abstr
|
||||
}
|
||||
|
||||
try {
|
||||
ConfigurationNode translation = getTranslationRoot();
|
||||
if (translation == null) {
|
||||
ConfigurationNode translationRoot = getTranslationRoot();
|
||||
if (translationRoot == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
translation = translation.node(config.getFileName());
|
||||
String fileIdentifier = config.getFileName();
|
||||
ConfigurationNode translation = translationRoot.node(fileIdentifier);
|
||||
ConfigurationNode comments = translationRoot.node(fileIdentifier + "_comments");
|
||||
|
||||
CommentedConfigurationNode node = loader().createNode();
|
||||
save(config, (Class<T>) config.getClass(), node);
|
||||
//node.set(config);
|
||||
translateNode(node, translation, translation.node("_comments"));
|
||||
translateNode(node, translation, comments);
|
||||
} catch (ConfigurateException e) {
|
||||
throw new ConfigException(e);
|
||||
}
|
||||
@ -96,13 +100,14 @@ public abstract class TranslatedConfigManager<T extends Config, LT extends Abstr
|
||||
ConfigurationNode translations,
|
||||
ConfigurationNode commentTranslations
|
||||
) throws SerializationException {
|
||||
Object[] path = node.path().array();
|
||||
List<Object> path = new ArrayList<>(Arrays.asList(node.path().array()));
|
||||
|
||||
String translation = translations.node(path).getString();
|
||||
if (translation != null) {
|
||||
node.set(translation);
|
||||
}
|
||||
|
||||
path.add("_comment");
|
||||
String commentTranslation = commentTranslations.node(path).getString();
|
||||
if (commentTranslation != null) {
|
||||
node.comment(commentTranslation);
|
||||
|
@ -54,6 +54,6 @@ public class ColorSerializer implements TypeSerializer<Color> {
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
node.set(obj.hex());
|
||||
node.set("#" + obj.hex());
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import org.spongepowered.configurate.util.NamingScheme;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class DiscordMessageEmbedSerializer implements TypeSerializer<DiscordMessageEmbed.Builder> {
|
||||
|
||||
@ -53,7 +54,7 @@ public class DiscordMessageEmbedSerializer implements TypeSerializer<DiscordMess
|
||||
Color color = node.node(map("Color")).get(Color.class);
|
||||
builder.setColor(color != null ? color.rgb() : Role.DEFAULT_COLOR_RAW);
|
||||
|
||||
ConfigurationNode author = node.node("Author");
|
||||
ConfigurationNode author = node.node(map("Author"));
|
||||
builder.setAuthor(
|
||||
author.node(map("Name")).getString(),
|
||||
author.node(map("Url")).getString(),
|
||||
@ -65,7 +66,7 @@ public class DiscordMessageEmbedSerializer implements TypeSerializer<DiscordMess
|
||||
title.node(map("Url")).getString());
|
||||
|
||||
builder.setDescription(node.node(map("Description")).getString());
|
||||
for (DiscordMessageEmbed.Field field : node.getList(DiscordMessageEmbed.Field.class, Collections.emptyList())) {
|
||||
for (DiscordMessageEmbed.Field field : node.node(map("Fields")).getList(DiscordMessageEmbed.Field.class, Collections.emptyList())) {
|
||||
builder.addField(field);
|
||||
}
|
||||
|
||||
@ -77,7 +78,7 @@ public class DiscordMessageEmbedSerializer implements TypeSerializer<DiscordMess
|
||||
ConfigurationNode footer = node.node(map("Footer"));
|
||||
builder.setFooter(
|
||||
footer.node(map("Text")).getString(),
|
||||
footer.node(map("ImageUrl")).getString(footer.node(map("IconUrl")).getString()));
|
||||
footer.node(map("ImageUrl")).getString(footer.node(map("IconUrl")).getString("")));
|
||||
|
||||
return builder;
|
||||
}
|
||||
@ -102,7 +103,10 @@ public class DiscordMessageEmbedSerializer implements TypeSerializer<DiscordMess
|
||||
title.node(map("Url")).set(obj.getTitleUrl());
|
||||
|
||||
node.node(map("Description")).set(obj.getDescription());
|
||||
node.node(map("Fields")).setList(DiscordMessageEmbed.Field.class, obj.getFields());
|
||||
|
||||
List<DiscordMessageEmbed.Field> fields = obj.getFields();
|
||||
ConfigurationNode fieldsNode = node.node(map("Fields"));
|
||||
fieldsNode.setList(DiscordMessageEmbed.Field.class, fields.isEmpty() ? null : obj.getFields());
|
||||
|
||||
node.node(map("ThumbnailUrl")).set(obj.getThumbnailUrl());
|
||||
node.node(map("ImageUrl")).set(obj.getImageUrl());
|
||||
|
@ -19,7 +19,7 @@
|
||||
package com.discordsrv.common.console;
|
||||
|
||||
import com.discordsrv.common.command.game.sender.ICommandSender;
|
||||
import com.discordsrv.logging.backend.LoggingBackend;
|
||||
import com.discordsrv.common.logging.backend.LoggingBackend;
|
||||
|
||||
public interface Console extends ICommandSender {
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
package com.discordsrv.common.dependency;
|
||||
|
||||
import com.discordsrv.logging.Logger;
|
||||
import com.discordsrv.common.logging.Logger;
|
||||
import com.discordsrv.common.scheduler.threadfactory.CountingForkJoinWorkerThreadFactory;
|
||||
import dev.vankka.dependencydownload.classpath.ClasspathAppender;
|
||||
|
||||
|
@ -30,8 +30,8 @@ import com.discordsrv.api.discord.api.entity.guild.DiscordRole;
|
||||
import com.discordsrv.api.discord.api.exception.NotReadyException;
|
||||
import com.discordsrv.api.discord.api.exception.RestErrorResponseException;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.config.main.channels.BaseChannelConfig;
|
||||
import com.discordsrv.common.config.main.channels.ChannelConfig;
|
||||
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
|
||||
import com.discordsrv.common.config.main.channels.base.IChannelConfig;
|
||||
import com.discordsrv.common.discord.api.channel.DiscordDMChannelImpl;
|
||||
import com.discordsrv.common.discord.api.channel.DiscordTextChannelImpl;
|
||||
import com.discordsrv.common.discord.api.guild.DiscordGuildImpl;
|
||||
@ -208,7 +208,7 @@ public class DiscordAPIImpl implements DiscordAPI {
|
||||
}).thenApply(webhook ->
|
||||
WebhookClientBuilder.fromJDA(webhook)
|
||||
.setHttpClient(jda.getHttpClient())
|
||||
.setExecutorService(discordSRV.scheduler().executor())
|
||||
.setExecutorService(discordSRV.scheduler().scheduledExecutor())
|
||||
.build()
|
||||
);
|
||||
}
|
||||
@ -218,8 +218,8 @@ public class DiscordAPIImpl implements DiscordAPI {
|
||||
|
||||
private boolean isConfiguredChannel(Long channelId) {
|
||||
for (BaseChannelConfig config : discordSRV.config().channels.values()) {
|
||||
if (config instanceof ChannelConfig
|
||||
&& ((ChannelConfig) config).channelIds.contains(channelId)) {
|
||||
if (config instanceof IChannelConfig
|
||||
&& ((IChannelConfig) config).ids().contains(channelId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -25,12 +25,12 @@ import com.discordsrv.api.discord.api.entity.guild.DiscordRole;
|
||||
import com.discordsrv.api.placeholder.annotation.Placeholder;
|
||||
import com.discordsrv.api.placeholder.annotation.PlaceholderRemainder;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.component.util.ComponentUtil;
|
||||
import com.discordsrv.common.discord.api.DiscordUserImpl;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -107,20 +107,19 @@ public class DiscordGuildMemberImpl extends DiscordUserImpl implements DiscordGu
|
||||
return null;
|
||||
}
|
||||
|
||||
@Placeholder("user_roles_")
|
||||
@Placeholder("user_roles")
|
||||
public Component _allRoles(@PlaceholderRemainder String suffix) {
|
||||
if (suffix.startsWith("_")) {
|
||||
suffix = suffix.substring(1);
|
||||
} else if (!suffix.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Component> components = new ArrayList<>();
|
||||
for (DiscordRole role : getRoles()) {
|
||||
components.add(Component.text(role.getName()).color(TextColor.color(role.getColor().rgb())));
|
||||
}
|
||||
|
||||
TextComponent.Builder builder = Component.text();
|
||||
for (int i = 0; i < components.size(); i++) {
|
||||
builder.append(components.get(i));
|
||||
if (i < components.size() - 1) {
|
||||
builder.append(Component.text(suffix));
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
return ComponentUtil.join(Component.text(suffix), components);
|
||||
}
|
||||
}
|
||||
|
@ -36,18 +36,20 @@ import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage;
|
||||
import com.discordsrv.api.discord.api.entity.message.impl.SendableDiscordMessageImpl;
|
||||
import com.discordsrv.api.discord.api.exception.RestErrorResponseException;
|
||||
import com.discordsrv.api.placeholder.annotation.Placeholder;
|
||||
import com.discordsrv.api.placeholder.annotation.PlaceholderRemainder;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.component.util.ComponentUtil;
|
||||
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
|
||||
import com.discordsrv.common.discord.api.DiscordUserImpl;
|
||||
import com.discordsrv.common.discord.api.channel.DiscordMessageChannelImpl;
|
||||
import com.discordsrv.common.discord.api.guild.DiscordGuildMemberImpl;
|
||||
import com.discordsrv.common.function.OrDefault;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import net.dv8tion.jda.api.requests.ErrorResponse;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -287,18 +289,24 @@ public class ReceivedDiscordMessageImpl extends SendableDiscordMessageImpl imple
|
||||
//
|
||||
|
||||
@Placeholder("message_attachments")
|
||||
public Component _attachments() {
|
||||
// TODO: customizable
|
||||
|
||||
TextComponent.Builder builder = Component.text();
|
||||
for (Attachment attachment : attachments) {
|
||||
builder.append(
|
||||
Component.text()
|
||||
.content("[" + attachment.fileName() + "]")
|
||||
.clickEvent(ClickEvent.openUrl(attachment.url()))
|
||||
)
|
||||
.append(Component.text(" "));
|
||||
public Component _attachments(OrDefault<BaseChannelConfig> config, @PlaceholderRemainder String suffix) {
|
||||
if (suffix.startsWith("_")) {
|
||||
suffix = suffix.substring(1);
|
||||
} else if (!suffix.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return builder.build();
|
||||
|
||||
String attachmentFormat = config.map(cfg -> cfg.discordToMinecraft).get(cfg -> cfg.attachmentFormat);
|
||||
List<Component> components = new ArrayList<>();
|
||||
for (Attachment attachment : attachments) {
|
||||
components.add(ComponentUtil.fromAPI(
|
||||
discordSRV.componentFactory().enhancedBuilder(attachmentFormat)
|
||||
.addReplacement("%file_name%", attachment.fileName())
|
||||
.addReplacement("%file_url%", attachment.url())
|
||||
.build()
|
||||
));
|
||||
}
|
||||
|
||||
return ComponentUtil.join(Component.text(suffix), components);
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.logging;
|
||||
package com.discordsrv.common.logging;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
@ -16,9 +16,9 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.logging.backend;
|
||||
package com.discordsrv.common.logging.backend;
|
||||
|
||||
import com.discordsrv.logging.LogLevel;
|
||||
import com.discordsrv.common.logging.LogLevel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
@ -16,7 +16,9 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.logging.backend;
|
||||
package com.discordsrv.common.logging.backend;
|
||||
|
||||
import com.discordsrv.common.logging.LogAppender;
|
||||
|
||||
public interface LoggingBackend {
|
||||
|
@ -16,11 +16,11 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.common.logging;
|
||||
package com.discordsrv.common.logging.dependency;
|
||||
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.logging.LogLevel;
|
||||
import com.discordsrv.logging.backend.LogAppender;
|
||||
import com.discordsrv.common.logging.LogLevel;
|
||||
import com.discordsrv.common.logging.LogAppender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@ -53,8 +53,8 @@ public class DependencyLoggingHandler implements LogAppender {
|
||||
@Override
|
||||
public void append(@Nullable String loggerName, @NotNull LogLevel logLevel, @Nullable String message,
|
||||
@Nullable Throwable throwable) {
|
||||
if (loggerName == null || !loggerName.startsWith("com.discordsrv.dependencies")) {
|
||||
return;
|
||||
if (loggerName == null) {
|
||||
loggerName = "null";
|
||||
}
|
||||
|
||||
if (message != null) {
|
@ -16,13 +16,13 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.logging.impl;
|
||||
package com.discordsrv.common.logging.impl;
|
||||
|
||||
import com.discordsrv.logging.LogLevel;
|
||||
import com.discordsrv.logging.Logger;
|
||||
import com.discordsrv.logging.backend.LogAppender;
|
||||
import com.discordsrv.logging.backend.LogFilter;
|
||||
import com.discordsrv.logging.backend.LoggingBackend;
|
||||
import com.discordsrv.common.logging.LogLevel;
|
||||
import com.discordsrv.common.logging.Logger;
|
||||
import com.discordsrv.common.logging.LogAppender;
|
||||
import com.discordsrv.common.logging.backend.LogFilter;
|
||||
import com.discordsrv.common.logging.backend.LoggingBackend;
|
||||
import org.apache.commons.collections4.bidimap.DualHashBidiMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
@ -16,13 +16,13 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.logging.impl;
|
||||
package com.discordsrv.common.logging.impl;
|
||||
|
||||
import com.discordsrv.logging.LogLevel;
|
||||
import com.discordsrv.logging.backend.LogAppender;
|
||||
import com.discordsrv.logging.backend.LogFilter;
|
||||
import com.discordsrv.logging.backend.LoggingBackend;
|
||||
import com.discordsrv.logging.Logger;
|
||||
import com.discordsrv.common.logging.LogLevel;
|
||||
import com.discordsrv.common.logging.LogAppender;
|
||||
import com.discordsrv.common.logging.backend.LogFilter;
|
||||
import com.discordsrv.common.logging.backend.LoggingBackend;
|
||||
import com.discordsrv.common.logging.Logger;
|
||||
import org.apache.commons.collections4.bidimap.DualHashBidiMap;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
@ -16,18 +16,18 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.logging.impl;
|
||||
package com.discordsrv.common.logging.impl;
|
||||
|
||||
import com.discordsrv.logging.LogLevel;
|
||||
import com.discordsrv.logging.Logger;
|
||||
import com.discordsrv.common.logging.LogLevel;
|
||||
import com.discordsrv.common.logging.Logger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class SLF4JLoggerImpl implements Logger {
|
||||
|
||||
private final org.slf4j.Logger logger;
|
||||
private final com.discordsrv.x.slf4j.Logger logger;
|
||||
|
||||
public SLF4JLoggerImpl(org.slf4j.Logger logger) {
|
||||
public SLF4JLoggerImpl(com.discordsrv.x.slf4j.Logger logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
@ -16,12 +16,14 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.common.proxy;
|
||||
package com.discordsrv.common.module;
|
||||
|
||||
import com.discordsrv.common.AbstractDiscordSRV;
|
||||
import com.discordsrv.common.config.connection.ConnectionConfig;
|
||||
import com.discordsrv.common.config.main.MainConfig;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.module.type.AbstractModule;
|
||||
|
||||
public abstract class ProxyDiscordSRV<C extends MainConfig, CC extends ConnectionConfig> extends AbstractDiscordSRV<C, CC> {
|
||||
@FunctionalInterface
|
||||
public interface ModuleInitializationFunction {
|
||||
|
||||
AbstractModule initialize(DiscordSRV discordSRV) throws Throwable;
|
||||
|
||||
}
|
@ -23,6 +23,8 @@ import com.discordsrv.api.event.bus.Subscribe;
|
||||
import com.discordsrv.api.event.events.lifecycle.DiscordSRVReloadEvent;
|
||||
import com.discordsrv.api.event.events.lifecycle.DiscordSRVShuttingDownEvent;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.module.type.AbstractModule;
|
||||
import com.discordsrv.common.module.type.Module;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -31,8 +33,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
public class ModuleManager {
|
||||
|
||||
private final Set<Module> modules = new CopyOnWriteArraySet<>();
|
||||
private final Map<String, Module> moduleLookupTable = new ConcurrentHashMap<>();
|
||||
private final Set<AbstractModule> modules = new CopyOnWriteArraySet<>();
|
||||
private final Map<String, AbstractModule> moduleLookupTable = new ConcurrentHashMap<>();
|
||||
private final DiscordSRV discordSRV;
|
||||
|
||||
public ModuleManager(DiscordSRV discordSRV) {
|
||||
@ -42,23 +44,25 @@ public class ModuleManager {
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Module> T getModule(Class<T> moduleType) {
|
||||
return (T) moduleLookupTable.computeIfAbsent(moduleType.getName(), key -> {
|
||||
for (Module module : modules) {
|
||||
if (moduleType.isAssignableFrom(module.getClass())) {
|
||||
return module;
|
||||
AbstractModule bestCandidate = null;
|
||||
for (AbstractModule module : modules) {
|
||||
if (moduleType.isAssignableFrom(module.getClass())
|
||||
&& (bestCandidate == null || module.priority() > bestCandidate.priority())) {
|
||||
bestCandidate = module;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return bestCandidate;
|
||||
});
|
||||
}
|
||||
|
||||
public void register(Module module) {
|
||||
public void register(AbstractModule module) {
|
||||
this.modules.add(module);
|
||||
this.moduleLookupTable.put(module.getClass().getName(), module);
|
||||
|
||||
enable(module);
|
||||
}
|
||||
|
||||
private void enable(Module module) {
|
||||
private void enable(AbstractModule module) {
|
||||
try {
|
||||
module.enableModule();
|
||||
} catch (Throwable t) {
|
||||
@ -66,14 +70,14 @@ public class ModuleManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void unregister(Module module) {
|
||||
public void unregister(AbstractModule module) {
|
||||
this.modules.remove(module);
|
||||
this.moduleLookupTable.values().removeIf(mod -> mod == module);
|
||||
|
||||
disable(module);
|
||||
}
|
||||
|
||||
private void disable(Module module) {
|
||||
private void disable(AbstractModule module) {
|
||||
try {
|
||||
module.disable();
|
||||
} catch (Throwable t) {
|
||||
@ -83,14 +87,14 @@ public class ModuleManager {
|
||||
|
||||
@Subscribe(priority = EventPriority.EARLY)
|
||||
public void onShuttingDown(DiscordSRVShuttingDownEvent event) {
|
||||
for (Module module : modules) {
|
||||
for (AbstractModule module : modules) {
|
||||
unregister(module);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(priority = EventPriority.EARLY)
|
||||
public void onReload(DiscordSRVReloadEvent event) {
|
||||
for (Module module : modules) {
|
||||
for (AbstractModule module : modules) {
|
||||
// Check if the module needs to be enabled due to reload
|
||||
enable(module);
|
||||
|
||||
|
@ -19,14 +19,14 @@
|
||||
package com.discordsrv.common.module.modules;
|
||||
|
||||
import com.discordsrv.api.event.bus.Subscribe;
|
||||
import com.discordsrv.api.event.events.discord.DiscordMessageReceivedEvent;
|
||||
import com.discordsrv.api.discord.events.DiscordMessageReceivedEvent;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.discord.api.channel.DiscordMessageChannelImpl;
|
||||
import com.discordsrv.common.discord.api.message.ReceivedDiscordMessageImpl;
|
||||
import com.discordsrv.common.module.Module;
|
||||
import com.discordsrv.common.module.type.AbstractModule;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
|
||||
public class DiscordAPIEventModule extends Module {
|
||||
public class DiscordAPIEventModule extends AbstractModule {
|
||||
|
||||
public DiscordAPIEventModule(DiscordSRV discordSRV) {
|
||||
super(discordSRV);
|
||||
|
@ -23,10 +23,9 @@ import com.discordsrv.api.event.bus.Subscribe;
|
||||
import com.discordsrv.api.event.events.channel.GameChannelLookupEvent;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.channel.DefaultGlobalChannel;
|
||||
import com.discordsrv.common.event.util.EventUtil;
|
||||
import com.discordsrv.common.module.Module;
|
||||
import com.discordsrv.common.module.type.AbstractModule;
|
||||
|
||||
public class GlobalChannelLookupModule extends Module {
|
||||
public class GlobalChannelLookupModule extends AbstractModule {
|
||||
|
||||
private final DefaultGlobalChannel defaultGlobalChannel;
|
||||
|
||||
@ -37,7 +36,7 @@ public class GlobalChannelLookupModule extends Module {
|
||||
|
||||
@Subscribe(priority = EventPriority.LATE)
|
||||
public void onGameChannelLookup(GameChannelLookupEvent event) {
|
||||
if (EventUtil.checkProcessor(discordSRV, event)) {
|
||||
if (checkProcessor(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2021 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.module.modules.integration;
|
||||
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.module.type.PermissionDataProvider;
|
||||
import com.discordsrv.common.module.type.PluginIntegration;
|
||||
import net.luckperms.api.LuckPerms;
|
||||
import net.luckperms.api.LuckPermsProvider;
|
||||
import net.luckperms.api.model.group.Group;
|
||||
import net.luckperms.api.model.user.User;
|
||||
import net.luckperms.api.query.QueryOptions;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
public class LuckPermsIntegration extends PluginIntegration implements PermissionDataProvider {
|
||||
|
||||
private LuckPerms luckPerms;
|
||||
|
||||
public LuckPermsIntegration(DiscordSRV discordSRV) {
|
||||
super(discordSRV);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
try {
|
||||
Class.forName("net.luckperms.api.LuckPerms");
|
||||
} catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
luckPerms = LuckPermsProvider.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
luckPerms = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasGroup(UUID player, String groupName) {
|
||||
User user = luckPerms.getUserManager().getUser(player);
|
||||
if (user == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Collection<Group> groups = user.getInheritedGroups(QueryOptions.defaultContextualOptions());
|
||||
return groups.stream().anyMatch(group -> group.getName().equalsIgnoreCase(groupName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addGroup(UUID player, String groupName) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeGroup(UUID player, String groupName) {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2021 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.module.modules.message;
|
||||
|
||||
import com.discordsrv.api.channel.GameChannel;
|
||||
import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessage;
|
||||
import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster;
|
||||
import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage;
|
||||
import com.discordsrv.api.discord.api.util.DiscordFormattingUtil;
|
||||
import com.discordsrv.api.event.events.message.receive.game.AbstractGameMessageReceiveEvent;
|
||||
import com.discordsrv.api.placeholder.FormattedText;
|
||||
import com.discordsrv.api.player.DiscordSRVPlayer;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.component.util.ComponentUtil;
|
||||
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
|
||||
import com.discordsrv.common.config.main.channels.base.IChannelConfig;
|
||||
import com.discordsrv.common.discord.api.message.ReceivedDiscordMessageClusterImpl;
|
||||
import com.discordsrv.common.function.OrDefault;
|
||||
import com.discordsrv.common.module.type.AbstractModule;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public abstract class AbstractGameMessageModule<T> extends AbstractModule {
|
||||
|
||||
public AbstractGameMessageModule(DiscordSRV discordSRV) {
|
||||
super(discordSRV);
|
||||
}
|
||||
|
||||
public abstract OrDefault<T> mapConfig(OrDefault<BaseChannelConfig> channelConfig);
|
||||
public abstract boolean isEnabled(OrDefault<T> config);
|
||||
public abstract SendableDiscordMessage.Builder getFormat(OrDefault<T> config);
|
||||
public abstract void postClusterToEventBus(ReceivedDiscordMessageCluster cluster);
|
||||
|
||||
public final void process(
|
||||
@NotNull AbstractGameMessageReceiveEvent event,
|
||||
@NotNull DiscordSRVPlayer player,
|
||||
@Nullable GameChannel channel
|
||||
) {
|
||||
if (channel == null) {
|
||||
// Send to all channels due to lack of specified channel
|
||||
for (OrDefault<BaseChannelConfig> channelConfig : discordSRV.channelConfig().getAllChannels()) {
|
||||
forwardToChannel(event, player, channelConfig);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
OrDefault<BaseChannelConfig> channelConfig = discordSRV.channelConfig().orDefault(channel);
|
||||
forwardToChannel(event, player, channelConfig);
|
||||
}
|
||||
|
||||
private void forwardToChannel(
|
||||
@NotNull AbstractGameMessageReceiveEvent event,
|
||||
@NotNull DiscordSRVPlayer player,
|
||||
@NotNull OrDefault<BaseChannelConfig> channelConfig
|
||||
) {
|
||||
OrDefault<T> config = mapConfig(channelConfig);
|
||||
if (!isEnabled(config)) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<Long> channelIds = channelConfig.get(cfg -> cfg instanceof IChannelConfig ? ((IChannelConfig) cfg).ids() : null);
|
||||
if (channelIds == null || channelIds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SendableDiscordMessage.Builder format = getFormat(config);
|
||||
if (format == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String message = convertMessage(config, ComponentUtil.fromAPI(event.getMessage()));
|
||||
List<CompletableFuture<ReceivedDiscordMessage>> futures = sendMessageToChannels(
|
||||
config, format, channelIds, message,
|
||||
// Context
|
||||
channelConfig, player
|
||||
);
|
||||
|
||||
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
|
||||
.whenComplete((v, t) -> {
|
||||
if (t != null) {
|
||||
discordSRV.logger().error("Failed to deliver message to Discord", t);
|
||||
return;
|
||||
}
|
||||
|
||||
List<ReceivedDiscordMessage> messages = new ArrayList<>();
|
||||
for (CompletableFuture<ReceivedDiscordMessage> future : futures) {
|
||||
// They are all done
|
||||
messages.add(future.join());
|
||||
}
|
||||
|
||||
postClusterToEventBus(new ReceivedDiscordMessageClusterImpl(messages));
|
||||
});
|
||||
}
|
||||
|
||||
public String convertMessage(OrDefault<T> config, Component component) {
|
||||
return DiscordFormattingUtil.escapeContent(
|
||||
discordSRV.componentFactory().discordSerializer().serialize(component)
|
||||
);
|
||||
}
|
||||
|
||||
public List<CompletableFuture<ReceivedDiscordMessage>> sendMessageToChannels(
|
||||
OrDefault<T> config,
|
||||
SendableDiscordMessage.Builder format,
|
||||
List<Long> channelIds,
|
||||
String message,
|
||||
Object... context
|
||||
) {
|
||||
SendableDiscordMessage discordMessage = format.toFormatter()
|
||||
.addContext(context)
|
||||
.addReplacement("%message%", new FormattedText(message))
|
||||
.applyPlaceholderService()
|
||||
.build();
|
||||
|
||||
List<CompletableFuture<ReceivedDiscordMessage>> futures = new ArrayList<>();
|
||||
for (Long channelId : channelIds) {
|
||||
discordSRV.discordAPI().getTextChannelById(channelId)
|
||||
.ifPresent(channel -> futures.add(channel.sendMessage(discordMessage)));
|
||||
}
|
||||
|
||||
return futures;
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.common.module.modules;
|
||||
package com.discordsrv.common.module.modules.message;
|
||||
|
||||
import com.discordsrv.api.channel.GameChannel;
|
||||
import com.discordsrv.api.component.EnhancedTextBuilder;
|
||||
@ -25,25 +25,25 @@ import com.discordsrv.api.discord.api.entity.DiscordUser;
|
||||
import com.discordsrv.api.discord.api.entity.channel.DiscordTextChannel;
|
||||
import com.discordsrv.api.discord.api.entity.guild.DiscordGuildMember;
|
||||
import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessage;
|
||||
import com.discordsrv.api.discord.events.DiscordMessageReceivedEvent;
|
||||
import com.discordsrv.api.event.bus.Subscribe;
|
||||
import com.discordsrv.api.event.events.discord.DiscordMessageReceivedEvent;
|
||||
import com.discordsrv.api.event.events.message.receive.discord.DiscordMessageProcessingEvent;
|
||||
import com.discordsrv.api.event.events.message.receive.discord.DiscordChatMessageProcessingEvent;
|
||||
import com.discordsrv.api.placeholder.util.Placeholders;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.component.renderer.DiscordSRVMinecraftRenderer;
|
||||
import com.discordsrv.common.component.util.ComponentUtil;
|
||||
import com.discordsrv.common.config.main.channels.BaseChannelConfig;
|
||||
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
|
||||
import com.discordsrv.common.config.main.channels.DiscordToMinecraftChatConfig;
|
||||
import com.discordsrv.common.function.OrDefault;
|
||||
import com.discordsrv.common.module.Module;
|
||||
import com.discordsrv.common.module.type.AbstractModule;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class DiscordToMinecraftModule extends Module {
|
||||
public class DiscordToMinecraftChatModule extends AbstractModule {
|
||||
|
||||
public DiscordToMinecraftModule(DiscordSRV discordSRV) {
|
||||
public DiscordToMinecraftChatModule(DiscordSRV discordSRV) {
|
||||
super(discordSRV);
|
||||
}
|
||||
|
||||
@ -54,30 +54,38 @@ public class DiscordToMinecraftModule extends Module {
|
||||
return;
|
||||
}
|
||||
|
||||
discordSRV.eventBus().publish(new DiscordMessageProcessingEvent(event.getMessage(), channel));
|
||||
discordSRV.eventBus().publish(new DiscordChatMessageProcessingEvent(event.getMessage(), channel));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onDiscordMessageReceive(DiscordMessageProcessingEvent event) {
|
||||
public void onDiscordMessageReceive(DiscordChatMessageProcessingEvent event) {
|
||||
if (checkCancellation(event) || checkProcessor(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<GameChannel, OrDefault<BaseChannelConfig>> channels = discordSRV.channelConfig().orDefault(event.getChannel());
|
||||
if (channels == null || channels.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Map.Entry<GameChannel, OrDefault<BaseChannelConfig>> entry : channels.entrySet()) {
|
||||
process(event, entry.getKey(), entry.getValue());
|
||||
}
|
||||
event.markAsProcessed();
|
||||
}
|
||||
|
||||
private void process(DiscordChatMessageProcessingEvent event, GameChannel gameChannel, OrDefault<BaseChannelConfig> channelConfig) {
|
||||
OrDefault<DiscordToMinecraftChatConfig> chatConfig = channelConfig.map(cfg -> cfg.discordToMinecraft);
|
||||
if (!chatConfig.get(cfg -> cfg.enabled, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DiscordTextChannel channel = event.getChannel();
|
||||
ReceivedDiscordMessage discordMessage = event.getDiscordMessage();
|
||||
DiscordUser author = discordMessage.getAuthor();
|
||||
Optional<DiscordGuildMember> member = discordMessage.getMember();
|
||||
boolean webhookMessage = discordMessage.isWebhookMessage();
|
||||
|
||||
OrDefault<Pair<GameChannel, BaseChannelConfig>> channelPair = discordSRV.channelConfig().orDefault(channel);
|
||||
GameChannel gameChannel = channelPair.get(Pair::getKey);
|
||||
if (gameChannel == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
OrDefault<? extends BaseChannelConfig> channelConfig = channelPair.map(Pair::getValue);
|
||||
OrDefault<DiscordToMinecraftChatConfig> chatConfig = channelConfig.map(cfg -> cfg.discordToMinecraft);
|
||||
|
||||
DiscordToMinecraftChatConfig.Ignores ignores = chatConfig.get(cfg -> cfg.ignores);
|
||||
if (ignores != null) {
|
||||
if (ignores.webhooks && webhookMessage) {
|
||||
@ -116,7 +124,7 @@ public class DiscordToMinecraftModule extends Module {
|
||||
|
||||
EnhancedTextBuilder componentBuilder = discordSRV.componentFactory()
|
||||
.enhancedBuilder(format)
|
||||
.addContext(discordMessage, author)
|
||||
.addContext(discordMessage, author, channel, channelConfig)
|
||||
.addReplacement("%message%", messageComponent);
|
||||
member.ifPresent(componentBuilder::addContext);
|
||||
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2021 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.module.modules.message;
|
||||
|
||||
import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster;
|
||||
import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage;
|
||||
import com.discordsrv.api.event.bus.EventPriority;
|
||||
import com.discordsrv.api.event.bus.Subscribe;
|
||||
import com.discordsrv.api.event.events.message.forward.game.JoinMessageForwardedEvent;
|
||||
import com.discordsrv.api.event.events.message.receive.game.JoinMessageReceiveEvent;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.config.main.channels.JoinMessageConfig;
|
||||
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
|
||||
import com.discordsrv.common.function.OrDefault;
|
||||
|
||||
public class JoinMessageModule extends AbstractGameMessageModule<JoinMessageConfig> {
|
||||
|
||||
public JoinMessageModule(DiscordSRV discordSRV) {
|
||||
super(discordSRV);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrDefault<JoinMessageConfig> mapConfig(OrDefault<BaseChannelConfig> channelConfig) {
|
||||
return channelConfig.map(cfg -> cfg.joinMessages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(OrDefault<JoinMessageConfig> config) {
|
||||
return config.get(cfg -> cfg.enabled, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SendableDiscordMessage.Builder getFormat(OrDefault<JoinMessageConfig> config) {
|
||||
return config.get(cfg -> cfg.format);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postClusterToEventBus(ReceivedDiscordMessageCluster cluster) {
|
||||
discordSRV.eventBus().publish(new JoinMessageForwardedEvent(cluster));
|
||||
}
|
||||
|
||||
@Subscribe(priority = EventPriority.LAST)
|
||||
public void onStatusMessageReceive(JoinMessageReceiveEvent event) {
|
||||
if (checkCancellation(event) || checkProcessor(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
process(event, event.getPlayer(), event.getGameChannel());
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user