diff --git a/src/main/java/buttondevteam/discordplugin/DPUtils.java b/src/main/java/buttondevteam/discordplugin/DPUtils.java index 069e675..6630839 100755 --- a/src/main/java/buttondevteam/discordplugin/DPUtils.java +++ b/src/main/java/buttondevteam/discordplugin/DPUtils.java @@ -46,7 +46,7 @@ public final class DPUtils { return sanitizedString.toString(); } - public static String escape(String message) { + private static String escape(String message) { return message.replaceAll("([*_~])", Matcher.quoteReplacement("\\") + "$1"); } @@ -69,15 +69,18 @@ public final class DPUtils { }, ch -> ch.getId().asLong()); //We can afford to search for the channel in the cache once (instead of using mainServer) } - public static ConfigData roleData(IHaveConfig config, String key, String defName) { - return roleData(config, key, defName, DiscordPlugin.mainServer); + public static ConfigData> roleData(IHaveConfig config, String key, String defName) { + return roleData(config, key, defName, Mono.just(DiscordPlugin.mainServer)); } - public static ConfigData roleData(IHaveConfig config, String key, String defName, Guild guild) { + /** + * Needs to be a {@link ConfigData} for checking if it's set + */ + public static ConfigData> roleData(IHaveConfig config, String key, String defName, Mono guild) { return config.getDataPrimDef(key, defName, name -> { - if (!(name instanceof String)) return null; - return guild.getRoles().filter(r -> r.getName().equals(name)).blockFirst(); - }, r -> r.getId().asLong()); + if (!(name instanceof String)) return Mono.empty(); + return guild.flatMapMany(Guild::getRoles).filter(r -> r.getName().equals(name)).last(); + }, r -> defName); } /** diff --git a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java index 307f8b9..4f7befb 100755 --- a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java +++ b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java @@ -16,6 +16,7 @@ import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.architecture.ButtonPlugin; import buttondevteam.lib.architecture.Component; import buttondevteam.lib.architecture.ConfigData; +import buttondevteam.lib.architecture.IHaveConfig; import buttondevteam.lib.player.ChromaGamerBase; import com.google.common.io.Files; import discord4j.core.DiscordClient; @@ -36,16 +37,17 @@ import org.bukkit.Bukkit; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.plugin.RegisteredServiceProvider; +import reactor.core.publisher.Mono; import java.awt.*; import java.io.File; import java.nio.charset.StandardCharsets; -import java.time.Duration; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; +@ButtonPlugin.ConfigOpts(disableConfigGen = true) public class DiscordPlugin extends ButtonPlugin { public static DiscordClient dc; public static DiscordPlugin plugin; @@ -53,7 +55,7 @@ public class DiscordPlugin extends ButtonPlugin { @Getter private Command2DC manager; - public ConfigData Prefix() { + private ConfigData Prefix() { return getIConfig().getData("prefix", '/', str -> ((String) str).charAt(0), Object::toString); } @@ -62,7 +64,7 @@ public class DiscordPlugin extends ButtonPlugin { return plugin.Prefix().get(); } - public ConfigData MainServer() { + private ConfigData MainServer() { return getIConfig().getDataPrimDef("mainServer", 219529124321034241L, id -> dc.getGuildById(Snowflake.of((long) id)).block(), g -> g.getId().asLong()); } @@ -70,7 +72,7 @@ public class DiscordPlugin extends ButtonPlugin { return DPUtils.channelData(getIConfig(), "commandChannel", 239519012529111040L); } - public ConfigData ModRole() { + public ConfigData> ModRole() { return DPUtils.roleData(getIConfig(), "modRole", "Moderator"); } @@ -193,6 +195,8 @@ public class DiscordPlugin extends ButtonPlugin { ChromaGamerBase.addConverter(sender -> Optional.ofNullable(sender instanceof DiscordSenderBase ? ((DiscordSenderBase) sender).getChromaUser() : null)); setupProviders(); + + IHaveConfig.pregenConfig(this, null); } catch (Exception e) { TBMCCoreAPI.SendException("An error occured while enabling DiscordPlugin!", e); } @@ -220,7 +224,7 @@ public class DiscordPlugin extends ButtonPlugin { + (Bukkit.getOnlinePlayers().size() == 1 ? " was " : " were ") + "kicked the hell out.") //TODO: Make configurable : ""); //If 'restart' is disabled then this isn't shown even if joinleave is enabled - }).block(Duration.ofSeconds(5)), ChannelconBroadcast.RESTART, false); + }).block(), ChannelconBroadcast.RESTART, false); ChromaBot.getInstance().updatePlayerList(); } diff --git a/src/main/java/buttondevteam/discordplugin/commands/Command2DC.java b/src/main/java/buttondevteam/discordplugin/commands/Command2DC.java index a0b8fda..4f5d0ec 100644 --- a/src/main/java/buttondevteam/discordplugin/commands/Command2DC.java +++ b/src/main/java/buttondevteam/discordplugin/commands/Command2DC.java @@ -3,6 +3,8 @@ package buttondevteam.discordplugin.commands; import buttondevteam.discordplugin.DiscordPlugin; import buttondevteam.lib.chat.Command2; +import java.lang.reflect.Method; + public class Command2DC extends Command2 { @Override public void registerCommand(ICommand2DC command) { @@ -10,7 +12,7 @@ public class Command2DC extends Command2 { } @Override - public boolean hasPermission(Command2DCSender sender, ICommand2DC command) { + public boolean hasPermission(Command2DCSender sender, ICommand2DC command, Method method) { //return !command.isModOnly() || sender.getMessage().getAuthor().hasRole(DiscordPlugin.plugin.ModRole().get()); //TODO: ModRole may be null; more customisable way? return true; } diff --git a/src/main/java/buttondevteam/discordplugin/commands/DebugCommand.java b/src/main/java/buttondevteam/discordplugin/commands/DebugCommand.java index e75a163..96d00b3 100644 --- a/src/main/java/buttondevteam/discordplugin/commands/DebugCommand.java +++ b/src/main/java/buttondevteam/discordplugin/commands/DebugCommand.java @@ -12,7 +12,8 @@ public class DebugCommand extends ICommand2DC { @Command2.Subcommand public boolean def(Command2DCSender sender, String args) { sender.getMessage().getAuthorAsMember() - .map(m -> m.getRoleIds().stream().anyMatch(r -> r.equals(DiscordPlugin.plugin.ModRole().get().getId()))) + .flatMap(m -> DiscordPlugin.plugin.ModRole().get() + .map(mr -> m.getRoleIds().stream().anyMatch(r -> r.equals(mr.getId())))) .subscribe(success -> { if (success) sender.sendMessage("debug " + (CommonListeners.debug() ? "enabled" : "disabled")); diff --git a/src/main/java/buttondevteam/discordplugin/exceptions/ExceptionListenerModule.java b/src/main/java/buttondevteam/discordplugin/exceptions/ExceptionListenerModule.java index 098ade3..a4d4848 100755 --- a/src/main/java/buttondevteam/discordplugin/exceptions/ExceptionListenerModule.java +++ b/src/main/java/buttondevteam/discordplugin/exceptions/ExceptionListenerModule.java @@ -15,6 +15,7 @@ import org.apache.commons.lang.exception.ExceptionUtils; import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import reactor.core.publisher.Mono; import java.util.ArrayList; import java.util.Arrays; @@ -22,51 +23,58 @@ import java.util.List; import java.util.stream.Collectors; public class ExceptionListenerModule extends Component implements Listener { - private List lastthrown = new ArrayList<>(); - private List lastsourcemsg = new ArrayList<>(); + private List lastthrown = new ArrayList<>(); + private List lastsourcemsg = new ArrayList<>(); - @EventHandler - public void onException(TBMCExceptionEvent e) { - if (DiscordPlugin.SafeMode || !ComponentManager.isEnabled(getClass())) - return; - if (lastthrown.stream() - .anyMatch(ex -> Arrays.equals(e.getException().getStackTrace(), ex.getStackTrace()) - && (e.getException().getMessage() == null ? ex.getMessage() == null - : e.getException().getMessage().equals(ex.getMessage()))) // e.Exception.Message==ex.Message - && lastsourcemsg.contains(e.getSourceMessage())) - return; - SendException(e.getException(), e.getSourceMessage()); - if (lastthrown.size() >= 10) - lastthrown.remove(0); - if (lastsourcemsg.size() >= 10) - lastsourcemsg.remove(0); - lastthrown.add(e.getException()); - lastsourcemsg.add(e.getSourceMessage()); - e.setHandled(); - } + @EventHandler + public void onException(TBMCExceptionEvent e) { + if (DiscordPlugin.SafeMode || !ComponentManager.isEnabled(getClass())) + return; + if (lastthrown.stream() + .anyMatch(ex -> Arrays.equals(e.getException().getStackTrace(), ex.getStackTrace()) + && (e.getException().getMessage() == null ? ex.getMessage() == null + : e.getException().getMessage().equals(ex.getMessage()))) // e.Exception.Message==ex.Message + && lastsourcemsg.contains(e.getSourceMessage())) + return; + SendException(e.getException(), e.getSourceMessage()); + if (lastthrown.size() >= 10) + lastthrown.remove(0); + if (lastsourcemsg.size() >= 10) + lastsourcemsg.remove(0); + lastthrown.add(e.getException()); + lastsourcemsg.add(e.getSourceMessage()); + e.setHandled(); + } - private static void SendException(Throwable e, String sourcemessage) { + private static void SendException(Throwable e, String sourcemessage) { if (instance == null) return; - try { + try { MessageChannel channel = getChannel(); - assert channel != null; - Role coderRole = instance.pingRole(((GuildChannel) channel).getGuild().block()).get(); - StringBuilder sb = TBMCCoreAPI.IsTestServer() ? new StringBuilder() - : new StringBuilder(coderRole == null ? "" : coderRole.getMention()).append("\n"); - sb.append(sourcemessage).append("\n"); - sb.append("```").append("\n"); - String stackTrace = Arrays.stream(ExceptionUtils.getStackTrace(e).split("\\n")) - .filter(s -> !s.contains("\tat ") || s.contains("\tat buttondevteam.")) - .collect(Collectors.joining("\n")); - if (sb.length() + stackTrace.length() >= 2000) - stackTrace = stackTrace.substring(0, 1999 - sb.length()); - sb.append(stackTrace).append("\n"); - sb.append("```"); - channel.createMessage(sb.toString()).subscribe(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + assert channel != null; + Mono coderRole; + if (channel instanceof GuildChannel) + coderRole = instance.pingRole(((GuildChannel) channel).getGuild()).get(); + else + coderRole = Mono.empty(); + coderRole.map(role -> TBMCCoreAPI.IsTestServer() ? new StringBuilder() + : new StringBuilder(role.getMention()).append("\n")) + .defaultIfEmpty(new StringBuilder()) + .flatMap(sb -> { + sb.append(sourcemessage).append("\n"); + sb.append("```").append("\n"); + String stackTrace = Arrays.stream(ExceptionUtils.getStackTrace(e).split("\\n")) + .filter(s -> !s.contains("\tat ") || s.contains("\tat buttondevteam.")) + .collect(Collectors.joining("\n")); + if (sb.length() + stackTrace.length() >= 2000) + stackTrace = stackTrace.substring(0, 1999 - sb.length()); + sb.append(stackTrace).append("\n"); + sb.append("```"); + return channel.createMessage(sb.toString()); + }).subscribe(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } private static ExceptionListenerModule instance; @@ -79,7 +87,7 @@ public class ExceptionListenerModule extends Component implements return DPUtils.channelData(getConfig(), "channel", 239519012529111040L); } - private ConfigData pingRole(Guild guild) { + private ConfigData> pingRole(Mono guild) { return DPUtils.roleData(getConfig(), "pingRole", "Coder", guild); } diff --git a/src/main/java/buttondevteam/discordplugin/fun/FunModule.java b/src/main/java/buttondevteam/discordplugin/fun/FunModule.java index 0ccc4b9..ac9e423 100644 --- a/src/main/java/buttondevteam/discordplugin/fun/FunModule.java +++ b/src/main/java/buttondevteam/discordplugin/fun/FunModule.java @@ -15,6 +15,7 @@ import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; +import reactor.core.publisher.Mono; import java.util.ArrayList; import java.util.Arrays; @@ -114,7 +115,7 @@ public class FunModule extends Component implements Listener { ListC = 0; } - private ConfigData fullHouseDevRole(Guild guild) { + private ConfigData> fullHouseDevRole(Mono guild) { return DPUtils.roleData(getConfig(), "fullHouseDevRole", "Developer", guild); } @@ -131,20 +132,21 @@ public class FunModule extends Component implements Listener { if (fm == null) return; val channel = fm.fullHouseChannel().get(); if (channel == null) return; - val devrole = fm.fullHouseDevRole(((GuildChannel) channel).getGuild().block()).get(); + if (!(channel instanceof GuildChannel)) return; + val devrole = fm.fullHouseDevRole(((GuildChannel) channel).getGuild()).get(); if (devrole == null) return; if (event.getOld().map(p -> p.getStatus().equals(Status.OFFLINE)).orElse(false) && !event.getCurrent().getStatus().equals(Status.OFFLINE) - && event.getMember().flatMap(m -> m.getRoles() - .any(r -> r.getId().asLong() == devrole.getId().asLong())).block() - && event.getGuild().flatMap(g -> g.getMembers().filter(m -> m.getRoleIds().stream().anyMatch(s -> s.equals(devrole.getId()))) + && event.getMember().flatMap(m -> devrole.flatMap(dr -> m.getRoles() + .any(r -> r.getId().asLong() == dr.getId().asLong()))).block() + && event.getGuild().flatMap(g -> devrole.flatMapMany(dr -> g.getMembers().filter(m -> m.getRoleIds().stream().anyMatch(s -> s.equals(dr.getId())))) .flatMap(Member::getPresence).all(pr -> !pr.getStatus().equals(Status.OFFLINE))).block() && lasttime + 10 < TimeUnit.NANOSECONDS.toHours(System.nanoTime()) && Calendar.getInstance().get(Calendar.DAY_OF_MONTH) % 5 == 0) { channel.createMessage(mcs -> mcs.setContent("Full house!").setEmbed(ecs -> ecs.setImage( "https://cdn.discordapp.com/attachments/249295547263877121/249687682618359808/poker-hand-full-house-aces-kings-playing-cards-15553791.png") - )); + )).subscribe(); lasttime = TimeUnit.NANOSECONDS.toHours(System.nanoTime()); } } diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java index d4b6891..5d64aeb 100644 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCListener.java @@ -1,13 +1,11 @@ package buttondevteam.discordplugin.mcchat; import buttondevteam.discordplugin.*; -import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.TBMCSystemChatEvent; import buttondevteam.lib.architecture.ConfigData; import buttondevteam.lib.player.*; import com.earth2me.essentials.CommandSource; import discord4j.core.object.entity.Role; -import discord4j.core.object.entity.User; import discord4j.core.object.util.Snowflake; import lombok.RequiredArgsConstructor; import lombok.val; @@ -101,13 +99,13 @@ class MCListener implements Listener { MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(msg), base, ChannelconBroadcast.AFK, false); } - private ConfigData muteRole() { + private ConfigData> muteRole() { return DPUtils.roleData(module.getConfig(), "muteRole", "Muted"); } @EventHandler public void onPlayerMute(MuteStatusChangeEvent e) { - final Role role = muteRole().get(); + final Mono role = muteRole().get(); if (role == null) return; final CommandSource source = e.getAffected().getSource(); if (!source.isPlayer()) @@ -117,18 +115,18 @@ class MCListener implements Listener { if (p == null) return; DiscordPlugin.dc.getUserById(Snowflake.of(p.getDiscordID())) .flatMap(user -> user.asMember(DiscordPlugin.mainServer.getId())) - .flatMap(user -> { + .flatMap(user -> role.flatMap(r -> { if (e.getValue()) - user.addRole(role.getId()); + user.addRole(r.getId()); else - user.removeRole(role.getId()); + user.removeRole(r.getId()); val modlog = module.modlogChannel().get(); String msg = (e.getValue() ? "M" : "Unm") + "uted user: " + user.getUsername() + "#" + user.getDiscriminator(); DPUtils.getLogger().info(msg); if (modlog != null) return modlog.createMessage(msg); return Mono.empty(); - }).subscribe(); + })).subscribe(); } @EventHandler