From b68456e6f44d669de1c740b44ed4621d45b9db2f Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sat, 4 May 2019 03:11:03 +0200 Subject: [PATCH] Even more fixes Actually made the channel data return a Mono and used that Used the read only config stuff #93 --- .../buttondevteam/discordplugin/DPUtils.java | 54 +++++++++++-------- .../discordplugin/DiscordPlugin.java | 13 +++-- .../announcer/AnnouncerModule.java | 19 ++++--- .../exceptions/ExceptionListenerModule.java | 11 ++-- .../discordplugin/fun/FunModule.java | 42 +++++++-------- .../listeners/CommandListener.java | 2 +- .../listeners/CommonListeners.java | 2 +- .../discordplugin/mcchat/MCChatListener.java | 13 ++--- .../mcchat/MinecraftChatModule.java | 12 +++-- 9 files changed, 98 insertions(+), 70 deletions(-) diff --git a/src/main/java/buttondevteam/discordplugin/DPUtils.java b/src/main/java/buttondevteam/discordplugin/DPUtils.java index 6630839..45a8e53 100755 --- a/src/main/java/buttondevteam/discordplugin/DPUtils.java +++ b/src/main/java/buttondevteam/discordplugin/DPUtils.java @@ -4,7 +4,11 @@ import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.architecture.Component; import buttondevteam.lib.architecture.ConfigData; import buttondevteam.lib.architecture.IHaveConfig; -import discord4j.core.object.entity.*; +import buttondevteam.lib.architecture.ReadOnlyConfigData; +import discord4j.core.object.entity.Guild; +import discord4j.core.object.entity.Message; +import discord4j.core.object.entity.MessageChannel; +import discord4j.core.object.entity.Role; import discord4j.core.object.util.Snowflake; import discord4j.core.spec.EmbedCreateSpec; import lombok.val; @@ -56,43 +60,36 @@ public final class DPUtils { return DiscordPlugin.plugin.getLogger(); } - public static ConfigData channelData(IHaveConfig config, String key, long defID) { - return config.getDataPrimDef(key, defID, id -> { - Channel ch = DiscordPlugin.dc.getChannelById(Snowflake.of((long) id)).onErrorResume(e -> { - getLogger().warning("Failed to get channel data for " + key + "=" + id + " - " + e.getMessage()); - return Mono.empty(); - }).block(); - if (ch instanceof MessageChannel) - return (MessageChannel) ch; - else - return null; - }, ch -> ch.getId().asLong()); //We can afford to search for the channel in the cache once (instead of using mainServer) + public static ReadOnlyConfigData> channelData(IHaveConfig config, String key, long defID) { + return config.getReadOnlyDataPrimDef(key, defID, id -> getMessageChannel(key, Snowflake.of((Long) id)), ch -> defID); //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) { + public static ReadOnlyConfigData> roleData(IHaveConfig config, String key, String defName) { return roleData(config, key, defName, Mono.just(DiscordPlugin.mainServer)); } /** * 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 -> { + public static ReadOnlyConfigData> roleData(IHaveConfig config, String key, String defName, Mono guild) { + return config.getReadOnlyDataPrimDef(key, defName, name -> { if (!(name instanceof String)) return Mono.empty(); return guild.flatMapMany(Guild::getRoles).filter(r -> r.getName().equals(name)).last(); }, r -> defName); } + public static ConfigData snowflakeData(IHaveConfig config, String key, long defID) { + return config.getDataPrimDef(key, defID, id -> Snowflake.of((long) id), Snowflake::asLong); + } + /** * Mentions the bot channel. Useful for help texts. * * @return The string for mentioning the channel */ public static String botmention() { - Channel channel; - if (DiscordPlugin.plugin == null - || (channel = DiscordPlugin.plugin.CommandChannel().get()) == null) return "#bot"; - return channel.getMention(); + if (DiscordPlugin.plugin == null) return "#bot"; + return channelMention(DiscordPlugin.plugin.CommandChannel().get()); } /** @@ -104,14 +101,14 @@ public final class DPUtils { */ public static boolean disableIfConfigError(@Nullable Component component, ConfigData... configs) { for (val config : configs) { - if (config.get() == null) { + Object v = config.get(); + //noinspection ConstantConditions + if (v == null || (v instanceof Mono && !((Mono) v).hasElement().block())) { String path = null; try { if (component != null) Component.setComponentEnabled(component, false); - val f = ConfigData.class.getDeclaredField("path"); - f.setAccessible(true); //Hacking my own plugin - path = (String) f.get(config); + path = config.getPath(); } catch (Exception e) { TBMCCoreAPI.SendException("Failed to disable component after config error!", e); } @@ -137,4 +134,15 @@ public final class DPUtils { return "<@!" + userId.asString() + ">"; } + public static String channelMention(Snowflake channelId) { + return "<#" + channelId.asString() + ">"; + } + + public static Mono getMessageChannel(String key, Snowflake id) { + return DiscordPlugin.dc.getChannelById(id).onErrorResume(e -> { + getLogger().warning("Failed to get channel data for " + key + "=" + id + " - " + e.getMessage()); + return Mono.empty(); + }).filter(ch -> ch instanceof MessageChannel).cast(MessageChannel.class); + } + } diff --git a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java index 4f7befb..75e22d7 100755 --- a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java +++ b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java @@ -24,7 +24,6 @@ import discord4j.core.DiscordClientBuilder; import discord4j.core.event.domain.guild.GuildCreateEvent; import discord4j.core.event.domain.lifecycle.ReadyEvent; import discord4j.core.object.entity.Guild; -import discord4j.core.object.entity.MessageChannel; import discord4j.core.object.entity.Role; import discord4j.core.object.presence.Activity; import discord4j.core.object.presence.Presence; @@ -68,8 +67,8 @@ public class DiscordPlugin extends ButtonPlugin { return getIConfig().getDataPrimDef("mainServer", 219529124321034241L, id -> dc.getGuildById(Snowflake.of((long) id)).block(), g -> g.getId().asLong()); } - public ConfigData CommandChannel() { - return DPUtils.channelData(getIConfig(), "commandChannel", 239519012529111040L); + public ConfigData CommandChannel() { + return DPUtils.snowflakeData(getIConfig(), "commandChannel", 239519012529111040L); } public ConfigData> ModRole() { @@ -210,7 +209,9 @@ public class DiscordPlugin extends ButtonPlugin { @Override public void pluginPreDisable() { if (ChromaBot.getInstance() == null) return; //Failed to load + System.out.println("Disable start"); MCChatUtils.forCustomAndAllMCChat(ch -> ch.createEmbed(ecs -> { + System.out.println("Sending message to " + ch.getMention()); if (DiscordMCCommand.resetting) ecs.setColor(Color.ORANGE).setTitle("Discord plugin restarting"); else @@ -225,12 +226,16 @@ public class DiscordPlugin extends ButtonPlugin { + "kicked the hell out.") //TODO: Make configurable : ""); //If 'restart' is disabled then this isn't shown even if joinleave is enabled }).block(), ChannelconBroadcast.RESTART, false); + System.out.println("Updating player list"); ChromaBot.getInstance().updatePlayerList(); + System.out.println("Done"); } @Override public void pluginDisable() { + System.out.println("Actual disable start (logout)"); MCChatPrivate.logoutAll(); + System.out.println("Config setup"); getConfig().set("serverup", false); if (ChromaBot.getInstance() == null) return; //Failed to load @@ -238,7 +243,9 @@ public class DiscordPlugin extends ButtonPlugin { try { SafeMode = true; // Stop interacting with Discord ChromaBot.delete(); + System.out.println("Updating presence..."); dc.updatePresence(Presence.idle(Activity.playing("Chromacraft"))).block(); //No longer using the same account for testing + System.out.println("Logging out..."); dc.logout().block(); //Configs are emptied so channels and servers are fetched again } catch (Exception e) { diff --git a/src/main/java/buttondevteam/discordplugin/announcer/AnnouncerModule.java b/src/main/java/buttondevteam/discordplugin/announcer/AnnouncerModule.java index 690a085..afde743 100644 --- a/src/main/java/buttondevteam/discordplugin/announcer/AnnouncerModule.java +++ b/src/main/java/buttondevteam/discordplugin/announcer/AnnouncerModule.java @@ -6,6 +6,7 @@ import buttondevteam.discordplugin.DiscordPlugin; import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.architecture.Component; import buttondevteam.lib.architecture.ConfigData; +import buttondevteam.lib.architecture.ReadOnlyConfigData; import buttondevteam.lib.player.ChromaGamerBase; import com.google.gson.JsonArray; import com.google.gson.JsonElement; @@ -16,19 +17,22 @@ import discord4j.core.object.entity.MessageChannel; import lombok.val; import org.bukkit.configuration.file.YamlConfiguration; import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; import java.io.File; -import java.util.Objects; public class AnnouncerModule extends Component { /** * Channel to post new posts. */ - public ConfigData channel() { + public ReadOnlyConfigData> channel() { return DPUtils.channelData(getConfig(), "channel", 239519012529111040L); } - public ConfigData modChannel() { + /** + * Channel where distinguished (moderator) posts go. + */ + public ReadOnlyConfigData> modChannel() { return DPUtils.channelData(getConfig(), "modChannel", 239519012529111040L); } @@ -56,8 +60,7 @@ public class AnnouncerModule extends Component { stop = false; //If not the first time val keepPinned = keepPinned().get(); if (keepPinned == 0) return; - val channel = channel().get(); - Flux msgs = channel.getPinnedMessages(); + Flux msgs = channel().get().flatMapMany(MessageChannel::getPinnedMessages); msgs.subscribe(Message::unpin); val yc = YamlConfiguration.loadConfiguration(new File("plugins/DiscordPlugin", "config.yml")); //Name change if (lastannouncementtime().get() == 0) //Load old data @@ -118,9 +121,11 @@ public class AnnouncerModule extends Component { } } if (msgsb.length() > 0) - Objects.requireNonNull(channel().get().createMessage(msgsb.toString()).block()).pin().block(); + channel().get().flatMap(ch -> ch.createMessage(msgsb.toString())) + .flatMap(Message::pin).subscribe(); if (modmsgsb.length() > 0) - modChannel().get().createMessage(modmsgsb.toString()).block(); + modChannel().get().flatMap(ch -> ch.createMessage(modmsgsb.toString())) + .flatMap(Message::pin).subscribe(); if (lastannouncementtime().get() != lastanntime) lastannouncementtime().set(lastanntime); // If sending succeeded } catch (Exception e) { diff --git a/src/main/java/buttondevteam/discordplugin/exceptions/ExceptionListenerModule.java b/src/main/java/buttondevteam/discordplugin/exceptions/ExceptionListenerModule.java index a4d4848..45ac2c7 100755 --- a/src/main/java/buttondevteam/discordplugin/exceptions/ExceptionListenerModule.java +++ b/src/main/java/buttondevteam/discordplugin/exceptions/ExceptionListenerModule.java @@ -7,6 +7,7 @@ import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.TBMCExceptionEvent; import buttondevteam.lib.architecture.Component; import buttondevteam.lib.architecture.ConfigData; +import buttondevteam.lib.architecture.ReadOnlyConfigData; import discord4j.core.object.entity.Guild; import discord4j.core.object.entity.GuildChannel; import discord4j.core.object.entity.MessageChannel; @@ -49,7 +50,7 @@ public class ExceptionListenerModule extends Component implements private static void SendException(Throwable e, String sourcemessage) { if (instance == null) return; try { - MessageChannel channel = getChannel(); + Mono channel = getChannel(); assert channel != null; Mono coderRole; if (channel instanceof GuildChannel) @@ -69,7 +70,7 @@ public class ExceptionListenerModule extends Component implements stackTrace = stackTrace.substring(0, 1999 - sb.length()); sb.append(stackTrace).append("\n"); sb.append("```"); - return channel.createMessage(sb.toString()); + return channel.flatMap(ch -> ch.createMessage(sb.toString())); }).subscribe(); } catch (Exception ex) { ex.printStackTrace(); @@ -78,12 +79,12 @@ public class ExceptionListenerModule extends Component implements private static ExceptionListenerModule instance; - public static MessageChannel getChannel() { + public static Mono getChannel() { if (instance != null) return instance.channel().get(); - return null; + return Mono.empty(); } - private ConfigData channel() { + private ReadOnlyConfigData> channel() { return DPUtils.channelData(getConfig(), "channel", 239519012529111040L); } diff --git a/src/main/java/buttondevteam/discordplugin/fun/FunModule.java b/src/main/java/buttondevteam/discordplugin/fun/FunModule.java index ac9e423..9866334 100644 --- a/src/main/java/buttondevteam/discordplugin/fun/FunModule.java +++ b/src/main/java/buttondevteam/discordplugin/fun/FunModule.java @@ -6,6 +6,7 @@ import buttondevteam.discordplugin.DiscordPlugin; import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.architecture.Component; import buttondevteam.lib.architecture.ConfigData; +import buttondevteam.lib.architecture.ReadOnlyConfigData; import com.google.common.collect.Lists; import discord4j.core.event.domain.PresenceUpdateEvent; import discord4j.core.object.entity.*; @@ -120,34 +121,33 @@ public class FunModule extends Component implements Listener { } - private ConfigData fullHouseChannel() { + private ReadOnlyConfigData> fullHouseChannel() { return DPUtils.channelData(getConfig(), "fullHouseChannel", 219626707458457603L); } private static long lasttime = 0; - @SuppressWarnings("ConstantConditions") public static void handleFullHouse(PresenceUpdateEvent event) { val fm = ComponentManager.getIfEnabled(FunModule.class); if (fm == null) return; - val channel = fm.fullHouseChannel().get(); - if (channel == null) return; - 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 -> 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()); - } + if (Calendar.getInstance().get(Calendar.DAY_OF_MONTH) % 5 != 0) return; + fm.fullHouseChannel().get() + .filter(ch -> ch instanceof GuildChannel) + .flatMap(channel -> fm.fullHouseDevRole(((GuildChannel) channel).getGuild()).get() + .filter(role -> event.getOld().map(p -> p.getStatus().equals(Status.OFFLINE)).orElse(false)) + .filter(role -> !event.getCurrent().getStatus().equals(Status.OFFLINE)) + .filterWhen(devrole -> event.getMember().flatMap(m -> m.getRoles() + .any(r -> r.getId().asLong() == devrole.getId().asLong()))) + .filterWhen(devrole -> + event.getGuild().flatMapMany(g -> g.getMembers().filter(m -> m.getRoleIds().stream().anyMatch(s -> s.equals(devrole.getId())))) + .flatMap(Member::getPresence).all(pr -> !pr.getStatus().equals(Status.OFFLINE))) + .filter(devrole -> lasttime + 10 < TimeUnit.NANOSECONDS.toHours(System.nanoTime())) //This should stay so it checks this last + .flatMap(devrole -> { + lasttime = TimeUnit.NANOSECONDS.toHours(System.nanoTime()); + return 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(); } } diff --git a/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java b/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java index aff8339..ccd36f3 100644 --- a/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java @@ -27,7 +27,7 @@ public class CommandListener { if (!mentionedonly) { //mentionedonly conditions are in CommonListeners if (!(channel instanceof PrivateChannel) && !(content.charAt(0) == DiscordPlugin.getPrefix() - && channel.getId().asString().equals(DiscordPlugin.plugin.CommandChannel().get().getId().asString()))) // + && channel.getId().asString().equals(DiscordPlugin.plugin.CommandChannel().get().asString()))) // return false; channel.type().subscribe(); // Fun } diff --git a/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java b/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java index 6c55615..0f7ee85 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/CommonListeners.java @@ -40,7 +40,7 @@ public class CommonListeners { try { boolean handled = false; val commandChannel = DiscordPlugin.plugin.CommandChannel().get(); - if ((commandChannel != null && event.getMessage().getChannelId().asLong() == commandChannel.getId().asLong()) //If mentioned, that's higher than chat + if ((commandChannel != null && event.getMessage().getChannelId().asLong() == commandChannel.asLong()) //If mentioned, that's higher than chat || event.getMessage().getContent().orElse("").contains("channelcon")) //Only 'channelcon' is allowed in other channels handled = CommandListener.runCommand(event.getMessage(), true); //#bot is handled here if (handled) return; diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java index f013c1b..f843450 100755 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MCChatListener.java @@ -17,6 +17,7 @@ import com.vdurmont.emoji.EmojiParser; import discord4j.core.event.domain.message.MessageCreateEvent; import discord4j.core.object.Embed; import discord4j.core.object.entity.*; +import discord4j.core.object.util.Snowflake; import discord4j.core.spec.EmbedCreateSpec; import lombok.val; import org.bukkit.Bukkit; @@ -110,17 +111,17 @@ public class MCChatListener implements Listener { }; // Checks if the given channel is different than where the message was sent from // Or if it was from MC - Predicate isdifferentchannel = ch -> !(e.getSender() instanceof DiscordSenderBase) - || ((DiscordSenderBase) e.getSender()).getChannel().getId().asLong() != ch.getId().asLong(); + Predicate isdifferentchannel = id -> !(e.getSender() instanceof DiscordSenderBase) + || ((DiscordSenderBase) e.getSender()).getChannel().getId().asLong() != id.asLong(); if (e.getChannel().isGlobal() && (e.isFromCommand() || isdifferentchannel.test(module.chatChannel().get()))) doit.accept(MCChatUtils.lastmsgdata == null - ? MCChatUtils.lastmsgdata = new MCChatUtils.LastMsgData(module.chatChannel().get(), null) + ? MCChatUtils.lastmsgdata = new MCChatUtils.LastMsgData(module.chatChannelMono().block(), null) : MCChatUtils.lastmsgdata); for (MCChatUtils.LastMsgData data : MCChatPrivate.lastmsgPerUser) { - if ((e.isFromCommand() || isdifferentchannel.test(data.channel)) + if ((e.isFromCommand() || isdifferentchannel.test(data.channel.getId())) && e.shouldSendTo(MCChatUtils.getSender(data.channel.getId(), data.user))) doit.accept(data); } @@ -128,7 +129,7 @@ public class MCChatListener implements Listener { val iterator = MCChatCustom.lastmsgCustom.iterator(); while (iterator.hasNext()) { val lmd = iterator.next(); - if ((e.isFromCommand() || isdifferentchannel.test(lmd.channel)) //Test if msg is from Discord + if ((e.isFromCommand() || isdifferentchannel.test(lmd.channel.getId())) //Test if msg is from Discord && e.getChannel().ID.equals(lmd.mcchannel.ID) //If it's from a command, the command msg has been deleted, so we need to send it && e.getGroupID().equals(lmd.groupID)) { //Check if this is the group we want to test - #58 if (e.shouldSendTo(lmd.dcp)) //Check original user's permissions @@ -222,7 +223,7 @@ public class MCChatListener implements Listener { val author = ev.getMessage().getAuthor(); final boolean hasCustomChat = MCChatCustom.hasCustomChat(ev.getMessage().getChannelId()); val channel = ev.getMessage().getChannel().block(); - if (ev.getMessage().getChannelId().asLong() != module.chatChannel().get().getId().asLong() + if (ev.getMessage().getChannelId().asLong() != module.chatChannel().get().asLong() && !(channel instanceof PrivateChannel && author.map(u -> MCChatPrivate.isMinecraftChatEnabled(u.getId().asString())).orElse(false) && !hasCustomChat)) diff --git a/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java b/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java index d7f1860..b4f8ec6 100644 --- a/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java +++ b/src/main/java/buttondevteam/discordplugin/mcchat/MinecraftChatModule.java @@ -8,12 +8,14 @@ import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.TBMCSystemChatEvent; import buttondevteam.lib.architecture.Component; import buttondevteam.lib.architecture.ConfigData; +import buttondevteam.lib.architecture.ReadOnlyConfigData; import com.google.common.collect.Lists; import discord4j.core.object.entity.MessageChannel; import discord4j.core.object.util.Snowflake; import lombok.Getter; import lombok.val; import org.bukkit.Bukkit; +import reactor.core.publisher.Mono; import java.util.ArrayList; import java.util.Objects; @@ -42,14 +44,18 @@ public class MinecraftChatModule extends Component { /** * The channel to use as the public Minecraft chat - everything public gets broadcasted here */ - public ConfigData chatChannel() { - return DPUtils.channelData(getConfig(), "chatChannel", 239519012529111040L); + public ConfigData chatChannel() { + return DPUtils.snowflakeData(getConfig(), "chatChannel", 239519012529111040L); + } + + public Mono chatChannelMono() { + return DPUtils.getMessageChannel(chatChannel().getPath(), chatChannel().get()); } /** * The channel where the plugin can log when it mutes a player on Discord because of a Minecraft mute */ - public ConfigData modlogChannel() { + public ReadOnlyConfigData> modlogChannel() { return DPUtils.channelData(getConfig(), "modlogChannel", 283840717275791360L); }