diff --git a/src/main/java/buttondevteam/discordplugin/ChromaBot.java b/src/main/java/buttondevteam/discordplugin/ChromaBot.java index e67b431..e597095 100755 --- a/src/main/java/buttondevteam/discordplugin/ChromaBot.java +++ b/src/main/java/buttondevteam/discordplugin/ChromaBot.java @@ -46,7 +46,7 @@ public class ChromaBot { } /** - * Send a message to the chat channel and private chats. + * Send a message to the chat channels and private chats. * * @param message * The message to send, duh @@ -72,7 +72,7 @@ public class ChromaBot { } /** - * Send a fancy message to the chat channel. This will show a bold text with a colored line. + * Send a fancy message to the chat channels. This will show a bold text with a colored line. * * @param message * The message to send, duh @@ -85,7 +85,7 @@ public class ChromaBot { } /** - * Send a fancy message to the chat channel. This will show a bold text with a colored line. + * Send a fancy message to the chat channels. This will show a bold text with a colored line. * * @param message * The message to send, duh @@ -100,7 +100,7 @@ public class ChromaBot { } /** - * Send a fancy message to the chat channel. This will show a bold text with a colored line. + * Send a fancy message to the chat channels. This will show a bold text with a colored line. * * @param message * The message to send, duh @@ -117,7 +117,7 @@ public class ChromaBot { } /** - * Send a message to the chat channel. This will show a bold text with a colored line. + * Send a message to the chat channels. This will show a bold text with a colored line. * * @param message * The message to send, duh diff --git a/src/main/java/buttondevteam/discordplugin/DPUtils.java b/src/main/java/buttondevteam/discordplugin/DPUtils.java index d7c3bcb..abc1f8f 100755 --- a/src/main/java/buttondevteam/discordplugin/DPUtils.java +++ b/src/main/java/buttondevteam/discordplugin/DPUtils.java @@ -58,10 +58,8 @@ public final class DPUtils { */ @Nullable public static T perform(IRequest action) { - System.out.println("performA"); if (DiscordPlugin.SafeMode) return null; - System.out.println("performB"); if (Thread.currentThread() == DiscordPlugin.mainThread) // TODO: Ignore shutdown message <-- // throw new RuntimeException("Tried to wait for a Discord request on the main thread. This could cause lag."); Bukkit.getLogger().warning("Waiting for a Discord request on the main thread!"); diff --git a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java index 2bbfa93..170c789 100755 --- a/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java +++ b/src/main/java/buttondevteam/discordplugin/DiscordPlugin.java @@ -4,6 +4,7 @@ import buttondevteam.discordplugin.commands.DiscordCommandBase; import buttondevteam.discordplugin.listeners.*; import buttondevteam.discordplugin.mccommands.DiscordMCCommandBase; import buttondevteam.lib.TBMCCoreAPI; +import buttondevteam.lib.chat.Channel; import buttondevteam.lib.chat.TBMCChatAPI; import buttondevteam.lib.player.ChromaGamerBase; import com.google.common.io.Files; @@ -32,6 +33,7 @@ import java.awt.*; import java.io.File; import java.nio.charset.StandardCharsets; import java.util.List; +import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -132,12 +134,26 @@ public class DiscordPlugin extends JavaPlugin implements IListener { task.cancel(); if (!sent) { new ChromaBot(this).updatePlayerList(); - //Get all roles with the default color - /*GameRoles = mainServer.getRoles().stream().filter(r -> { - System.out.println(r.getName()+" - "+r.getColor().toString()+" "+r.getColor().getAlpha()); - return r.getColor().getAlpha() == 0; - }).map(IRole::getName).collect(Collectors.toList()); //r=149,g=165,b=166*/ GameRoles = mainServer.getRoles().stream().filter(this::isGameRole).map(IRole::getName).collect(Collectors.toList()); + + val chcons = getConfig().getConfigurationSection("chcons"); + if (chcons != null) { + val chconkeys = chcons.getKeys(false); + for (val chconkey : chconkeys) { + val chcon = chcons.getConfigurationSection(chconkey); + val mcch = Channel.getChannels().stream().filter(ch -> ch.ID.equals(chcon.getString("mcchid"))).findAny(); + val ch = dc.getChannelByID(chcon.getLong("chid")); + val did = chcon.getLong("did"); + val dp = DiscordPlayer.getUser(Long.toString(did), DiscordPlayer.class); + val user = dc.fetchUser(did); + val dcp = new DiscordConnectedPlayer(user, ch, UUID.fromString(chcon.getString("mcuid")), chcon.getString("mcname")); + val groupid = chcon.getString("groupid"); + if (!mcch.isPresent() || ch == null || user == null || groupid == null) + continue; + MCChatListener.addCustomChat(ch, groupid, mcch.get(), dp, user, dcp); + } + } + DiscordCommandBase.registerCommands(); if (getConfig().getBoolean("serverup", false)) { ChromaBot.getInstance().sendMessage("", new EmbedBuilder().withColor(Color.YELLOW) @@ -210,6 +226,8 @@ public class DiscordPlugin extends JavaPlugin implements IListener { } public boolean isGameRole(IRole r) { + if (r.getGuild().getLongID() != mainServer.getLongID()) + return false; //Only allow on the main server val rc = new Color(149, 165, 166, 0); return r.getColor().equals(rc) && r.getPosition() < mainServer.getRoleByID(234343495735836672L).getPosition(); //Below the ChromaBot role @@ -223,16 +241,25 @@ public class DiscordPlugin extends JavaPlugin implements IListener { @Override public void onDisable() { stop = true; - System.out.println("X"); for (val entry : MCChatListener.ConnectedSenders.entrySet()) MCListener.callEventExcludingSome(new PlayerQuitEvent(entry.getValue(), "")); - System.out.println("Y"); getConfig().set("lastannouncementtime", lastannouncementtime); getConfig().set("lastseentime", lastseentime); getConfig().set("serverup", false); - System.out.println("Z"); + + val chcons = MCChatListener.getCustomChats(); + val chconsc = getConfig().createSection("chcons"); + for (val chcon : chcons) { + val chconc = chconsc.createSection(chcon.channel.getStringID()); + chconc.set("mcchid", chcon.mcchannel.ID); + chconc.set("chid", chcon.channel.getLongID()); + chconc.set("did", chcon.user.getLongID()); + chconc.set("mcuid", chcon.dcp.getUniqueId().toString()); + chconc.set("mcname", chcon.dcp.getName()); + chconc.set("groupid", chcon.groupID); + } + saveConfig(); - System.out.println("XX"); MCChatListener.forAllMCChat(ch -> DiscordPlugin.sendMessageToChannelWait(ch, "", new EmbedBuilder().withColor(Restart ? Color.ORANGE : Color.RED) .withTitle(Restart ? "Server restarting" : "Server stopping") @@ -245,19 +272,13 @@ public class DiscordPlugin extends JavaPlugin implements IListener { + "asked *politely* to leave the server for a bit.") : "") .build(), 5, TimeUnit.SECONDS)); - System.out.println("XY"); ChromaBot.getInstance().updatePlayerList(); try { - System.out.println("XZ"); SafeMode = true; // Stop interacting with Discord MCChatListener.stop(); - System.out.println("YX"); ChromaBot.delete(); - System.out.println("YY"); dc.changePresence(StatusType.IDLE, ActivityType.PLAYING, "Chromacraft"); //No longer using the same account for testing - System.out.println("YZ"); dc.logout(); - System.out.println("ZX"); } catch (Exception e) { TBMCCoreAPI.SendException("An error occured while disabling DiscordPlugin!", e); } @@ -346,12 +367,10 @@ public class DiscordPlugin extends JavaPlugin implements IListener { } public static IMessage sendMessageToChannelWait(IChannel channel, String message, EmbedObject embed) { - System.out.println("lol"); return sendMessageToChannel(channel, message, embed, true); } public static IMessage sendMessageToChannelWait(IChannel channel, String message, EmbedObject embed, long timeout, TimeUnit unit) { - System.out.println("lol!"); return sendMessageToChannel(channel, message, embed, true, timeout, unit); } @@ -360,26 +379,19 @@ public class DiscordPlugin extends JavaPlugin implements IListener { } private static IMessage sendMessageToChannel(IChannel channel, String message, EmbedObject embed, boolean wait, long timeout, TimeUnit unit) { - System.out.println("lolwut"); if (message.length() > 1980) { - System.out.println("wut"); message = message.substring(0, 1980); Bukkit.getLogger() .warning("Message was too long to send to discord and got truncated. In " + channel.getName()); - System.out.println("wat"); } - System.out.println("wot"); try { - System.out.println("sendA"); if (channel == chatchannel) MCChatListener.resetLastMessage(); // If this is a chat message, it'll be set again else if (channel.isPrivate()) MCChatListener.resetLastMessage(channel); - System.out.println("sendB"); final String content = message; RequestBuffer.IRequest r = () -> embed == null ? channel.sendMessage(content) : channel.sendMessage(content, embed, false); - System.out.println("sendC"); if (wait) { if (unit != null) return DPUtils.perform(r, timeout, unit); diff --git a/src/main/java/buttondevteam/discordplugin/commands/ChannelconCommand.java b/src/main/java/buttondevteam/discordplugin/commands/ChannelconCommand.java index 44c88a7..d9a1c8f 100644 --- a/src/main/java/buttondevteam/discordplugin/commands/ChannelconCommand.java +++ b/src/main/java/buttondevteam/discordplugin/commands/ChannelconCommand.java @@ -28,7 +28,6 @@ public class ChannelconCommand extends DiscordCommandBase { message.reply("you need to have manage permissions for this channel!"); return true; } - //TODO: What if they no longer have permission to view the channel - check on some message events and startup - if somebody who can view the channel (on both platforms) has their accounts connected, keep it if (MCChatListener.hasCustomChat(message.getChannel())) { if (args.equalsIgnoreCase("remove")) { if (MCChatListener.removeCustomChat(message.getChannel())) @@ -51,14 +50,19 @@ public class ChannelconCommand extends DiscordCommandBase { message.reply("you need to connect your Minecraft account. On our server in #bot do /connect "); return true; } - val ev = new TBMCChannelConnectFakeEvent(new DiscordConnectedPlayer(message.getAuthor(), message.getChannel(), chp.getUUID(), Bukkit.getOfflinePlayer(chp.getUUID()).getName()), chan.get()); + DiscordConnectedPlayer dcp = new DiscordConnectedPlayer(message.getAuthor(), message.getChannel(), chp.getUUID(), Bukkit.getOfflinePlayer(chp.getUUID()).getName()); + val ev = new TBMCChannelConnectFakeEvent(dcp, chan.get()); //Using a fake player with no login/logout, should be fine for this event String groupid = ev.getGroupID(ev.getSender()); //We're not trying to send in a specific group, we want to know which group the user belongs to (so not getGroupID()) if (groupid == null) { message.reply("sorry, that didn't work. You cannot use that Minecraft channel."); return true; } - MCChatListener.addCustomChat(message.getChannel(), args, ev.getChannel(), dp, message.getAuthor()); //TODO: SAVE + if (MCChatListener.getCustomChats().stream().anyMatch(cc -> cc.groupID.equals(groupid) && cc.mcchannel.ID.equals(chan.get().ID))) { + message.reply("sorry, this MC chat is already connected to a different channel, multiple channels are not supported atm."); + return true; + } + MCChatListener.addCustomChat(message.getChannel(), groupid, ev.getChannel(), dp, message.getAuthor(), dcp); message.reply("alright, connection made to group `" + groupid + "`!"); return true; } diff --git a/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java b/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java index 12fbdbd..76ae457 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/CommandListener.java @@ -131,7 +131,7 @@ public class CommandListener { } }, (IListener) event -> { Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, () -> { - if (event.getRole().isDeleted() || DiscordPlugin.plugin.isGameRole(event.getRole())) + if (event.getRole().isDeleted() || !DiscordPlugin.plugin.isGameRole(event.getRole())) return; //Deleted or not a game role DiscordPlugin.GameRoles.add(event.getRole().getName()); DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Added " + event.getRole().getName() + " as game role. If you don't want this, change the role's color from the default."); @@ -216,7 +216,7 @@ public class CommandListener { else cmdwithargs.replace(0, cmdwithargs.length(), "help"); else { - if (cmdwithargs.charAt(0) == '/') + if (cmdwithargs.length() > 0 && cmdwithargs.charAt(0) == '/') cmdwithargs.deleteCharAt(0); //Don't treat / as mention, mentions can be used in public mcchat return false; } diff --git a/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java b/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java index 2754e63..d4a3ce9 100755 --- a/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java +++ b/src/main/java/buttondevteam/discordplugin/listeners/MCChatListener.java @@ -11,6 +11,7 @@ import buttondevteam.lib.chat.ChatRoom; import buttondevteam.lib.chat.TBMCChatAPI; import buttondevteam.lib.player.TBMCPlayer; import com.vdurmont.emoji.EmojiParser; +import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.val; import org.bukkit.Bukkit; @@ -34,9 +35,10 @@ import sx.blah.discord.util.MissingPermissionsException; import java.awt.*; import java.time.Instant; import java.util.*; +import java.util.List; import java.util.concurrent.LinkedBlockingQueue; -import java.util.function.BiConsumer; import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -142,8 +144,8 @@ public class MCChatListener implements Listener, IListener val lmd = iterator.next(); if ((e.isFromcmd() || isdifferentchannel.test(lmd.channel)) //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 - if (e.shouldSendTo(getSender(lmd.channel, lmd.user)) && e.getGroupID().equals(lmd.groupID)) - doit.accept(lmd); //TODO: Store dcp and check that both ways, add option to not check sender perms on msg + if (e.shouldSendTo(lmd.dcp) && e.getGroupID().equals(lmd.groupID)) //Check original user's permissions + doit.accept(lmd); else { iterator.remove(); //If the user no longer has permission, remove the connection DiscordPlugin.sendMessageToChannel(lmd.channel, "The user no longer has permission to view the channel, connection removed."); @@ -155,7 +157,7 @@ public class MCChatListener implements Listener, IListener } @RequiredArgsConstructor - private static class LastMsgData { + public static class LastMsgData { public IMessage message; public long time; public String content; @@ -165,15 +167,17 @@ public class MCChatListener implements Listener, IListener public final DiscordPlayer dp; } - private static class CustomLMD extends LastMsgData { + public static class CustomLMD extends LastMsgData { public final String groupID; public final Channel mcchannel; + public final DiscordConnectedPlayer dcp; - public CustomLMD(IChannel channel, IUser user, DiscordPlayer dp, String groupid, Channel mcchannel) { + public CustomLMD(@NonNull IChannel channel, @NonNull IUser user, @NonNull DiscordPlayer dp, + @NonNull String groupid, @NonNull Channel mcchannel, @NonNull DiscordConnectedPlayer dcp) { super(channel, user, dp); groupID = groupid; this.mcchannel = mcchannel; - + this.dcp = dcp; } } @@ -254,8 +258,8 @@ public class MCChatListener implements Listener, IListener .anyMatch(lmd -> ((IPrivateChannel) lmd.channel).getRecipient().getStringID().equals(did)); } - public static void addCustomChat(IChannel channel, String groupid, Channel mcchannel, DiscordPlayer dp, IUser user) { - val lmd = new CustomLMD(channel, user, dp, groupid, mcchannel); + public static void addCustomChat(IChannel channel, String groupid, Channel mcchannel, DiscordPlayer dp, IUser user, DiscordConnectedPlayer dcp) { + val lmd = new CustomLMD(channel, user, dp, groupid, mcchannel, dcp); lastmsgCustom.add(lmd); } @@ -271,6 +275,10 @@ public class MCChatListener implements Listener, IListener return lastmsgCustom.removeIf(lmd -> lmd.channel.getLongID() == channel.getLongID()); } + public static List getCustomChats() { + return Collections.unmodifiableList(lastmsgCustom); + } + /** * May contain P<DiscordID> as key for public chat */ @@ -312,12 +320,10 @@ public class MCChatListener implements Listener, IListener } public static void forAllMCChat(Consumer action) { - System.out.println("XA"); action.accept(DiscordPlugin.chatchannel); - System.out.println("XB"); for (LastMsgData data : lastmsgPerUser) action.accept(data.channel); - System.out.println("XC"); + lastmsgCustom.forEach(cc -> action.accept(cc.channel)); } private static void forAllowedMCChat(Consumer action, TBMCSystemChatEvent event) { @@ -326,6 +332,8 @@ public class MCChatListener implements Listener, IListener for (LastMsgData data : lastmsgPerUser) if (event.shouldSendTo(getSender(data.channel, data.user))) action.accept(data.channel); + lastmsgCustom.stream().filter(data -> event.shouldSendTo(data.dcp)) + .map(data -> data.channel).forEach(action); } public static void stop() { @@ -398,11 +406,12 @@ public class MCChatListener implements Listener, IListener dmessage = EmojiParser.parseToAliases(dmessage, EmojiParser.FitzpatrickAction.PARSE); //Converts emoji to text- TODO: Add option to disable (resource pack?) dmessage = dmessage.replaceAll(":(\\S+)\\|type_(?:(\\d)|(1)_2):", ":$1::skin-tone-$2:"); //Convert to Discord's format so it still shows up - BiConsumer sendChatMessage = (channel, msg) -> // - TBMCChatAPI.SendChatMessage(channel, dsender, - msg + (event.getMessage().getAttachments().size() > 0 ? "\n" + event.getMessage() + Function getChatMessage = msg -> // + msg + (event.getMessage().getAttachments().size() > 0 ? "\n" + event.getMessage() .getAttachments().stream().map(a -> a.getUrl()).collect(Collectors.joining("\n")) - : "")); + : ""); + + CustomLMD clmd = getCustomChat(event.getChannel()); boolean react = false; @@ -411,7 +420,7 @@ public class MCChatListener implements Listener, IListener if (!event.getMessage().isDeleted() && !event.getChannel().isPrivate()) event.getMessage().delete(); }); - preprocessChat(dsender, dmessage); + //preprocessChat(dsender, dmessage); - Same is done below final String cmdlowercased = dmessage.substring(1).toLowerCase(); if (dsender instanceof DiscordSender && Arrays.stream(UnconnectedCmds) .noneMatch(s -> cmdlowercased.equals(s) || cmdlowercased.startsWith(s + " "))) { @@ -468,7 +477,11 @@ public class MCChatListener implements Listener, IListener dsender.sendMessage("You're now talking in: " + DPUtils.sanitizeString(dsender.getMcchannel().DisplayName)); } else { // Send single message - sendChatMessage.accept(chc, event.getMessage().getContent().substring(spi + 2)); + final String msg = event.getMessage().getContent().substring(spi + 2); + if (clmd == null) + TBMCChatAPI.SendChatMessage(chc, dsender, getChatMessage.apply(msg), true); + else + TBMCChatAPI.SendChatMessageDontCheckSender(chc, dsender, getChatMessage.apply(msg), true, clmd.dcp); react = true; } } @@ -481,20 +494,16 @@ public class MCChatListener implements Listener, IListener TBMCChatAPI.SendSystemMessage(Channel.GlobalChat, 0, "everyone", (dsender instanceof Player ? ((Player) dsender).getDisplayName() : dsender.getName()) + " pinned a message on Discord."); - else if (hasCustomChat(event.getChannel())) { - val cc = getCustomChat(event.getChannel()); - sendChatMessage.accept(cc.mcchannel, dmessage); - } else { - sendChatMessage.accept(dsender.getMcchannel(), dmessage); + else { + if (clmd != null) + TBMCChatAPI.SendChatMessageDontCheckSender(clmd.mcchannel, dsender, getChatMessage.apply(dmessage), false, clmd.dcp); + else + TBMCChatAPI.SendChatMessage(dsender.getMcchannel(), dsender, getChatMessage.apply(dmessage)); react = true; } } if (react) { try { - /* - * System.out.println("Got message: " + m.getContent() + " with embeds: " + m.getEmbeds().stream().map(e -> e.getTitle() + " " + e.getDescription()) - * .collect(Collectors.joining("\n"))); - */ if (lastmsgfromd != null) { DPUtils.perform(() -> lastmsgfromd.removeReaction(DiscordPlugin.dc.getOurUser(), DiscordPlugin.DELIVERED_REACTION)); // Remove it no matter what, we know it's there 99.99% of the time