Fixes and improvements (config)

Fixed occasional ConcurrentModificationException with the custom chat loading
Waiting much less on MC command responses (0.2s instead of 0.5s)
Made the #bot channel configurable
Linking the #bot channel everywhere it's mentioned
#51
This commit is contained in:
Norbi Peti 2019-01-10 01:45:45 +01:00
parent f13c8321cd
commit 93af5f66d2
No known key found for this signature in database
GPG key ID: DBA4C4549A927E56
11 changed files with 710 additions and 664 deletions

19
.editorconfig Normal file
View file

@ -0,0 +1,19 @@
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = false
indent_style = space
indent_size = 4
[*.json]
indent_style = space
indent_size = 2
[*.java]
indent_style = tab
tab_width = 4
[{*.yml, *.yaml}]
indent_style = space
indent_size = 2

View file

@ -1,6 +1,10 @@
package buttondevteam.discordplugin; package buttondevteam.discordplugin;
import buttondevteam.lib.architecture.ConfigData;
import buttondevteam.lib.architecture.IHaveConfig;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import sx.blah.discord.handle.obj.IChannel;
import sx.blah.discord.handle.obj.IIDLinkedObject;
import sx.blah.discord.util.EmbedBuilder; import sx.blah.discord.util.EmbedBuilder;
import sx.blah.discord.util.RequestBuffer; import sx.blah.discord.util.RequestBuffer;
import sx.blah.discord.util.RequestBuffer.IRequest; import sx.blah.discord.util.RequestBuffer.IRequest;
@ -103,4 +107,18 @@ public final class DPUtils {
return DiscordPlugin.plugin.getLogger(); return DiscordPlugin.plugin.getLogger();
} }
public static ConfigData<IChannel> channelData(IHaveConfig config, String key, long defID) {
return config.getDataPrimDef(key, defID, id -> DiscordPlugin.dc.getChannelByID((long) id), IIDLinkedObject::getLongID); //We can afford to search for the channel in the cache once (instead of using mainServer)
}
/**
* Mentions the <b>bot channel</b>. Useful for help texts.
*
* @return The string for mentioning the channel
*/
public static String botmention() {
if (DiscordPlugin.plugin == null) return "#bot";
return DiscordPlugin.plugin.CommandChannel().get().mention();
}
} }

View file

@ -1,450 +1,460 @@
package buttondevteam.discordplugin; package buttondevteam.discordplugin;
import buttondevteam.discordplugin.broadcaster.GeneralEventBroadcasterModule; import buttondevteam.discordplugin.broadcaster.GeneralEventBroadcasterModule;
import buttondevteam.discordplugin.commands.DiscordCommandBase; import buttondevteam.discordplugin.commands.DiscordCommandBase;
import buttondevteam.discordplugin.exceptions.ExceptionListenerModule; import buttondevteam.discordplugin.exceptions.ExceptionListenerModule;
import buttondevteam.discordplugin.listeners.CommonListeners; import buttondevteam.discordplugin.listeners.CommonListeners;
import buttondevteam.discordplugin.listeners.MCListener; import buttondevteam.discordplugin.listeners.MCListener;
import buttondevteam.discordplugin.mcchat.*; import buttondevteam.discordplugin.mcchat.*;
import buttondevteam.discordplugin.mccommands.DiscordMCCommandBase; import buttondevteam.discordplugin.mccommands.DiscordMCCommandBase;
import buttondevteam.discordplugin.mccommands.ResetMCCommand; import buttondevteam.discordplugin.mccommands.ResetMCCommand;
import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.architecture.ButtonPlugin; import buttondevteam.lib.architecture.ButtonPlugin;
import buttondevteam.lib.architecture.Component; import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.architecture.ConfigData; import buttondevteam.lib.architecture.ConfigData;
import buttondevteam.lib.chat.Channel; import buttondevteam.lib.chat.Channel;
import buttondevteam.lib.chat.TBMCChatAPI; import buttondevteam.lib.chat.TBMCChatAPI;
import buttondevteam.lib.player.ChromaGamerBase; import buttondevteam.lib.player.ChromaGamerBase;
import com.google.common.io.Files; import com.google.common.io.Files;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import lombok.val; import lombok.val;
import net.milkbowl.vault.permission.Permission; import net.milkbowl.vault.permission.Permission;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
import sx.blah.discord.api.ClientBuilder; import sx.blah.discord.api.ClientBuilder;
import sx.blah.discord.api.IDiscordClient; import sx.blah.discord.api.IDiscordClient;
import sx.blah.discord.api.events.IListener; import sx.blah.discord.api.events.IListener;
import sx.blah.discord.api.internal.json.objects.EmbedObject; import sx.blah.discord.api.internal.json.objects.EmbedObject;
import sx.blah.discord.handle.impl.events.ReadyEvent; import sx.blah.discord.handle.impl.events.ReadyEvent;
import sx.blah.discord.handle.impl.obj.ReactionEmoji; import sx.blah.discord.handle.impl.obj.ReactionEmoji;
import sx.blah.discord.handle.obj.*; import sx.blah.discord.handle.obj.*;
import sx.blah.discord.util.EmbedBuilder; import sx.blah.discord.util.EmbedBuilder;
import sx.blah.discord.util.RequestBuffer; import sx.blah.discord.util.RequestBuffer;
import java.awt.*; import java.awt.*;
import java.io.File; import java.io.File;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class DiscordPlugin extends ButtonPlugin implements IListener<ReadyEvent> { public class DiscordPlugin extends ButtonPlugin implements IListener<ReadyEvent> {
private static final String SubredditURL = "https://www.reddit.com/r/ChromaGamers"; private static final String SubredditURL = "https://www.reddit.com/r/ChromaGamers";
private static boolean stop = false; private static boolean stop = false;
public static IDiscordClient dc; public static IDiscordClient dc;
public static DiscordPlugin plugin; public static DiscordPlugin plugin;
public static boolean SafeMode = true; public static boolean SafeMode = true;
public static List<String> GameRoles; public static List<String> GameRoles;
public ConfigData<Character> Prefix() { public ConfigData<Character> Prefix() {
return getData("prefix", '/'); return getIConfig().getData("prefix", '/', str -> ((String) str).charAt(0), Object::toString);
} }
public static char getPrefix() { public static char getPrefix() {
if (plugin == null) return '/'; if (plugin == null) return '/';
return plugin.Prefix().get(); return plugin.Prefix().get();
} }
@Override public ConfigData<IGuild> MainServer() {
public void pluginEnable() { return getIConfig().getDataPrimDef("mainServer", 219529124321034241L, id -> dc.getGuildByID((long) id), IIDLinkedObject::getLongID);
stop = false; //If not the first time }
try {
Bukkit.getLogger().info("Initializing DiscordPlugin..."); public ConfigData<IChannel> CommandChannel() {
plugin = this; return DPUtils.channelData(getIConfig(), "commandChannel", 239519012529111040L);
lastannouncementtime = getConfig().getLong("lastannouncementtime"); }
lastseentime = getConfig().getLong("lastseentime");
ClientBuilder cb = new ClientBuilder(); @Override
cb.withToken(Files.readFirstLine(new File("TBMC", "Token.txt"), StandardCharsets.UTF_8)); public void pluginEnable() {
dc = cb.login(); stop = false; //If not the first time
dc.getDispatcher().registerListener(this); try {
} catch (Exception e) { Bukkit.getLogger().info("Initializing DiscordPlugin...");
e.printStackTrace(); plugin = this;
Bukkit.getPluginManager().disablePlugin(this); lastannouncementtime = getConfig().getLong("lastannouncementtime");
} lastseentime = getConfig().getLong("lastseentime");
} ClientBuilder cb = new ClientBuilder();
cb.withToken(Files.readFirstLine(new File("TBMC", "Token.txt"), StandardCharsets.UTF_8));
public static IChannel botchannel; dc = cb.login();
public static IChannel annchannel; dc.getDispatcher().registerListener(this);
public static IChannel genchannel; } catch (Exception e) {
public static IChannel chatchannel; e.printStackTrace();
public static IChannel botroomchannel; Bukkit.getPluginManager().disablePlugin(this);
public static IChannel modlogchannel; }
/** }
* Don't send messages, just receive, the same channel is used when testing
*/ public static IChannel botchannel; //Can be removed
public static IChannel officechannel; public static IChannel annchannel;
public static IChannel updatechannel; public static IChannel genchannel;
public static IChannel devofficechannel; public static IChannel chatchannel;
public static IGuild mainServer; public static IChannel botroomchannel;
public static IGuild devServer; public static IChannel modlogchannel;
/**
private static volatile BukkitTask task; * Don't send messages, just receive, the same channel is used when testing
private static volatile boolean sent = false; */
public static IChannel officechannel;
@Override public static IChannel updatechannel;
public void handle(ReadyEvent event) { public static IChannel devofficechannel;
try { public static IGuild mainServer;
dc.changePresence(StatusType.DND, ActivityType.PLAYING, "booting"); public static IGuild devServer;
task = Bukkit.getScheduler().runTaskTimerAsynchronously(this, () -> {
if (mainServer == null || devServer == null) { private static volatile BukkitTask task;
mainServer = event.getClient().getGuildByID(125813020357165056L); private static volatile boolean sent = false;
devServer = event.getClient().getGuildByID(219529124321034241L);
} @Override
if (mainServer == null || devServer == null) public void handle(ReadyEvent event) {
return; // Retry try {
if (!TBMCCoreAPI.IsTestServer()) { //Don't change conditions here, see mainServer=devServer=null in onDisable() dc.changePresence(StatusType.DND, ActivityType.PLAYING, "booting");
botchannel = mainServer.getChannelByID(209720707188260864L); // bot task = Bukkit.getScheduler().runTaskTimerAsynchronously(this, () -> {
annchannel = mainServer.getChannelByID(126795071927353344L); // announcements if (mainServer == null || devServer == null) {
genchannel = mainServer.getChannelByID(125813020357165056L); // general mainServer = event.getClient().getGuildByID(125813020357165056L);
chatchannel = mainServer.getChannelByID(249663564057411596L); // minecraft_chat devServer = event.getClient().getGuildByID(219529124321034241L);
botroomchannel = devServer.getChannelByID(239519012529111040L); // bot-room }
officechannel = devServer.getChannelByID(219626707458457603L); // developers-office if (mainServer == null || devServer == null)
updatechannel = devServer.getChannelByID(233724163519414272L); // server-updates return; // Retry
devofficechannel = officechannel; // developers-office if (!TBMCCoreAPI.IsTestServer()) { //Don't change conditions here, see mainServer=devServer=null in onDisable()
modlogchannel = mainServer.getChannelByID(283840717275791360L); // modlog botchannel = mainServer.getChannelByID(209720707188260864L); // bot
dc.changePresence(StatusType.ONLINE, ActivityType.PLAYING, "Chromacraft"); annchannel = mainServer.getChannelByID(126795071927353344L); // announcements
} else { genchannel = mainServer.getChannelByID(125813020357165056L); // general
botchannel = devServer.getChannelByID(239519012529111040L); // bot-room chatchannel = mainServer.getChannelByID(249663564057411596L); // minecraft_chat
annchannel = botchannel; // bot-room botroomchannel = devServer.getChannelByID(239519012529111040L); // bot-room
genchannel = botchannel; // bot-room officechannel = devServer.getChannelByID(219626707458457603L); // developers-office
botroomchannel = botchannel;// bot-room updatechannel = devServer.getChannelByID(233724163519414272L); // server-updates
chatchannel = botchannel;// bot-room devofficechannel = officechannel; // developers-office
officechannel = devServer.getChannelByID(219626707458457603L); // developers-office modlogchannel = mainServer.getChannelByID(283840717275791360L); // modlog
updatechannel = botchannel; dc.changePresence(StatusType.ONLINE, ActivityType.PLAYING, "Chromacraft");
devofficechannel = botchannel;// bot-room } else {
modlogchannel = botchannel; // bot-room botchannel = devServer.getChannelByID(239519012529111040L); // bot-room
dc.changePresence(StatusType.ONLINE, ActivityType.PLAYING, "testing"); annchannel = botchannel; // bot-room
} genchannel = botchannel; // bot-room
if (botchannel == null || annchannel == null || genchannel == null || botroomchannel == null botroomchannel = botchannel;// bot-room
|| chatchannel == null || officechannel == null || updatechannel == null) chatchannel = botchannel;// bot-room
return; // Retry officechannel = devServer.getChannelByID(219626707458457603L); // developers-office
SafeMode = false; updatechannel = botchannel;
if (task != null) devofficechannel = botchannel;// bot-room
task.cancel(); modlogchannel = botchannel; // bot-room
if (!sent) { dc.changePresence(StatusType.ONLINE, ActivityType.PLAYING, "testing");
new ChromaBot(this).updatePlayerList(); }
GameRoles = mainServer.getRoles().stream().filter(this::isGameRole).map(IRole::getName).collect(Collectors.toList()); if (botchannel == null || annchannel == null || genchannel == null || botroomchannel == null
|| chatchannel == null || officechannel == null || updatechannel == null)
val chcons = getConfig().getConfigurationSection("chcons"); return; // Retry
if (chcons != null) { SafeMode = false;
val chconkeys = chcons.getKeys(false); if (task != null)
for (val chconkey : chconkeys) { task.cancel();
val chcon = chcons.getConfigurationSection(chconkey); if (!sent) {
val mcch = Channel.getChannels().stream().filter(ch -> ch.ID.equals(chcon.getString("mcchid"))).findAny(); new ChromaBot(this).updatePlayerList();
val ch = dc.getChannelByID(chcon.getLong("chid")); GameRoles = mainServer.getRoles().stream().filter(this::isGameRole).map(IRole::getName).collect(Collectors.toList());
val did = chcon.getLong("did");
val user = dc.fetchUser(did); val chcons = getConfig().getConfigurationSection("chcons");
val dcp = new DiscordConnectedPlayer(user, ch, UUID.fromString(chcon.getString("mcuid")), chcon.getString("mcname")); if (chcons != null) {
val groupid = chcon.getString("groupid"); val chconkeys = chcons.getKeys(false);
val toggles = chcon.getInt("toggles"); for (val chconkey : chconkeys) {
if (!mcch.isPresent() || ch == null || user == null || groupid == null) val chcon = chcons.getConfigurationSection(chconkey);
continue; val mcch = Channel.getChannels().stream().filter(ch -> ch.ID.equals(chcon.getString("mcchid"))).findAny();
MCChatCustom.addCustomChat(ch, groupid, mcch.get(), user, dcp, toggles); val ch = dc.getChannelByID(chcon.getLong("chid"));
} val did = chcon.getLong("did");
} val user = dc.fetchUser(did);
val groupid = chcon.getString("groupid");
DiscordCommandBase.registerCommands(); val toggles = chcon.getInt("toggles");
if (ResetMCCommand.resetting) if (!mcch.isPresent() || ch == null || user == null || groupid == null)
ChromaBot.getInstance().sendMessageCustomAsWell("", new EmbedBuilder().withColor(Color.CYAN) continue;
.withTitle("Discord plugin restarted - chat connected.").build(), ChannelconBroadcast.RESTART); //Really important to note the chat, hmm Bukkit.getScheduler().runTask(this, () -> { //<-- Needed because of occasional ConcurrentModificationExceptions when creating the player (PermissibleBase)
else if (getConfig().getBoolean("serverup", false)) { val dcp = new DiscordConnectedPlayer(user, ch, UUID.fromString(chcon.getString("mcuid")), chcon.getString("mcname"));
ChromaBot.getInstance().sendMessageCustomAsWell("", new EmbedBuilder().withColor(Color.YELLOW) MCChatCustom.addCustomChat(ch, groupid, mcch.get(), user, dcp, toggles);
.withTitle("Server recovered from a crash - chat connected.").build(), ChannelconBroadcast.RESTART); });
val thr = new Throwable( }
"The server shut down unexpectedly. See the log of the previous run for more details."); }
thr.setStackTrace(new StackTraceElement[0]);
TBMCCoreAPI.SendException("The server crashed!", thr); DiscordCommandBase.registerCommands();
} else if (ResetMCCommand.resetting)
ChromaBot.getInstance().sendMessageCustomAsWell("", new EmbedBuilder().withColor(Color.GREEN) ChromaBot.getInstance().sendMessageCustomAsWell("", new EmbedBuilder().withColor(Color.CYAN)
.withTitle("Server started - chat connected.").build(), ChannelconBroadcast.RESTART); .withTitle("Discord plugin restarted - chat connected.").build(), ChannelconBroadcast.RESTART); //Really important to note the chat, hmm
else if (getConfig().getBoolean("serverup", false)) {
ResetMCCommand.resetting = false; //This is the last event handling this flag ChromaBot.getInstance().sendMessageCustomAsWell("", new EmbedBuilder().withColor(Color.YELLOW)
.withTitle("Server recovered from a crash - chat connected.").build(), ChannelconBroadcast.RESTART);
getConfig().set("serverup", true); val thr = new Throwable(
saveConfig(); "The server shut down unexpectedly. See the log of the previous run for more details.");
DPUtils.performNoWait(() -> { thr.setStackTrace(new StackTraceElement[0]);
try { TBMCCoreAPI.SendException("The server crashed!", thr);
List<IMessage> msgs = genchannel.getPinnedMessages(); } else
for (int i = msgs.size() - 1; i >= 10; i--) { // Unpin all pinned messages except the newest 10 ChromaBot.getInstance().sendMessageCustomAsWell("", new EmbedBuilder().withColor(Color.GREEN)
genchannel.unpin(msgs.get(i)); .withTitle("Server started - chat connected.").build(), ChannelconBroadcast.RESTART);
Thread.sleep(10);
} ResetMCCommand.resetting = false; //This is the last event handling this flag
} catch (InterruptedException ignore) {
} getConfig().set("serverup", true);
}); saveConfig();
sent = true; DPUtils.performNoWait(() -> {
if (TBMCCoreAPI.IsTestServer() && !dc.getOurUser().getName().toLowerCase().contains("test")) { try {
TBMCCoreAPI.SendException( List<IMessage> msgs = genchannel.getPinnedMessages();
"Won't load because we're in testing mode and not using a separate account.", for (int i = msgs.size() - 1; i >= 10; i--) { // Unpin all pinned messages except the newest 10
new Exception( genchannel.unpin(msgs.get(i));
"The plugin refuses to load until you change the token to a testing account.")); Thread.sleep(10);
Bukkit.getPluginManager().disablePlugin(this); }
} } catch (InterruptedException ignore) {
TBMCCoreAPI.SendUnsentExceptions(); }
TBMCCoreAPI.SendUnsentDebugMessages(); });
/*if (!TBMCCoreAPI.IsTestServer()) { sent = true;
final Calendar currentCal = Calendar.getInstance(); if (TBMCCoreAPI.IsTestServer() && !dc.getOurUser().getName().toLowerCase().contains("test")) {
final Calendar newCal = Calendar.getInstance(); TBMCCoreAPI.SendException(
currentCal.set(currentCal.get(Calendar.YEAR), currentCal.get(Calendar.MONTH), "Won't load because we're in testing mode and not using a separate account.",
currentCal.get(Calendar.DAY_OF_MONTH), 4, 10); new Exception(
if (currentCal.get(Calendar.DAY_OF_MONTH) % 9 == 0 && currentCal.before(newCal)) { "The plugin refuses to load until you change the token to a testing account. (The account needs to have \"test\" in it's name.)"));
Random rand = new Random(); Bukkit.getPluginManager().disablePlugin(this);
sendMessageToChannel(dc.getChannels().get(rand.nextInt(dc.getChannels().size())), }
"You could make a religion out of this"); TBMCCoreAPI.SendUnsentExceptions();
} TBMCCoreAPI.SendUnsentDebugMessages();
}*/ /*if (!TBMCCoreAPI.IsTestServer()) {
} final Calendar currentCal = Calendar.getInstance();
}, 0, 10); final Calendar newCal = Calendar.getInstance();
for (IListener<?> listener : CommonListeners.getListeners()) currentCal.set(currentCal.get(Calendar.YEAR), currentCal.get(Calendar.MONTH),
dc.getDispatcher().registerListener(listener); currentCal.get(Calendar.DAY_OF_MONTH), 4, 10);
Component.registerComponent(this, new GeneralEventBroadcasterModule()); if (currentCal.get(Calendar.DAY_OF_MONTH) % 9 == 0 && currentCal.before(newCal)) {
Component.registerComponent(this, new MinecraftChatModule()); Random rand = new Random();
Component.registerComponent(this, new ExceptionListenerModule()); sendMessageToChannel(dc.getChannels().get(rand.nextInt(dc.getChannels().size())),
TBMCCoreAPI.RegisterEventsForExceptions(new MCListener(), this); "You could make a religion out of this");
TBMCChatAPI.AddCommands(this, DiscordMCCommandBase.class); }
TBMCCoreAPI.RegisterUserClass(DiscordPlayer.class); }*/
ChromaGamerBase.addConverter(sender -> Optional.ofNullable(sender instanceof DiscordSenderBase }
? ((DiscordSenderBase) sender).getChromaUser() : null)); }, 0, 10);
new Thread(this::AnnouncementGetterThreadMethod).start(); for (IListener<?> listener : CommonListeners.getListeners())
setupProviders(); dc.getDispatcher().registerListener(listener);
} catch (Exception e) { Component.registerComponent(this, new GeneralEventBroadcasterModule());
TBMCCoreAPI.SendException("An error occured while enabling DiscordPlugin!", e); Component.registerComponent(this, new MinecraftChatModule());
} Component.registerComponent(this, new ExceptionListenerModule());
} TBMCCoreAPI.RegisterEventsForExceptions(new MCListener(), this);
TBMCChatAPI.AddCommands(this, DiscordMCCommandBase.class);
public boolean isGameRole(IRole r) { TBMCCoreAPI.RegisterUserClass(DiscordPlayer.class);
if (r.getGuild().getLongID() != mainServer.getLongID()) ChromaGamerBase.addConverter(sender -> Optional.ofNullable(sender instanceof DiscordSenderBase
return false; //Only allow on the main server ? ((DiscordSenderBase) sender).getChromaUser() : null));
val rc = new Color(149, 165, 166, 0); new Thread(this::AnnouncementGetterThreadMethod).start();
return r.getColor().equals(rc) setupProviders();
&& r.getPosition() < mainServer.getRoleByID(234343495735836672L).getPosition(); //Below the ChromaBot role } catch (Exception e) {
} TBMCCoreAPI.SendException("An error occured while enabling DiscordPlugin!", e);
}
/** }
* Always true, except when running "stop" from console
*/ public boolean isGameRole(IRole r) {
public static boolean Restart; if (r.getGuild().getLongID() != mainServer.getLongID())
return false; //Only allow on the main server
@Override val rc = new Color(149, 165, 166, 0);
public void pluginDisable() { return r.getColor().equals(rc)
stop = true; && r.getPosition() < mainServer.getRoleByID(234343495735836672L).getPosition(); //Below the ChromaBot role
MCChatPrivate.logoutAll(); }
getConfig().set("lastannouncementtime", lastannouncementtime);
getConfig().set("lastseentime", lastseentime); /**
getConfig().set("serverup", false); * Always true, except when running "stop" from console
*/
val chcons = MCChatCustom.getCustomChats(); public static boolean Restart;
val chconsc = getConfig().createSection("chcons");
for (val chcon : chcons) { @Override
val chconc = chconsc.createSection(chcon.channel.getStringID()); public void pluginDisable() {
chconc.set("mcchid", chcon.mcchannel.ID); stop = true;
chconc.set("chid", chcon.channel.getLongID()); MCChatPrivate.logoutAll();
chconc.set("did", chcon.user.getLongID()); getConfig().set("lastannouncementtime", lastannouncementtime);
chconc.set("mcuid", chcon.dcp.getUniqueId().toString()); getConfig().set("lastseentime", lastseentime);
chconc.set("mcname", chcon.dcp.getName()); getConfig().set("serverup", false);
chconc.set("groupid", chcon.groupID);
chconc.set("toggles", chcon.toggles); val chcons = MCChatCustom.getCustomChats();
} val chconsc = getConfig().createSection("chcons");
for (val chcon : chcons) {
saveConfig(); val chconc = chconsc.createSection(chcon.channel.getStringID());
EmbedObject embed; chconc.set("mcchid", chcon.mcchannel.ID);
if (ResetMCCommand.resetting) chconc.set("chid", chcon.channel.getLongID());
embed = new EmbedBuilder().withColor(Color.ORANGE).withTitle("Discord plugin restarting").build(); chconc.set("did", chcon.user.getLongID());
else chconc.set("mcuid", chcon.dcp.getUniqueId().toString());
embed = new EmbedBuilder().withColor(Restart ? Color.ORANGE : Color.RED) chconc.set("mcname", chcon.dcp.getName());
.withTitle(Restart ? "Server restarting" : "Server stopping") chconc.set("groupid", chcon.groupID);
.withDescription( chconc.set("toggles", chcon.toggles);
Bukkit.getOnlinePlayers().size() > 0 }
? (DPUtils
.sanitizeString(Bukkit.getOnlinePlayers().stream() saveConfig();
.map(Player::getDisplayName).collect(Collectors.joining(", "))) EmbedObject embed;
+ (Bukkit.getOnlinePlayers().size() == 1 ? " was " : " were ") if (ResetMCCommand.resetting)
+ "kicked the hell out.") //TODO: Make configurable embed = new EmbedBuilder().withColor(Color.ORANGE).withTitle("Discord plugin restarting").build();
: "") //If 'restart' is disabled then this isn't shown even if joinleave is enabled else
.build(); embed = new EmbedBuilder().withColor(Restart ? Color.ORANGE : Color.RED)
MCChatUtils.forCustomAndAllMCChat(ch -> { .withTitle(Restart ? "Server restarting" : "Server stopping")
try { .withDescription(
DiscordPlugin.sendMessageToChannelWait(ch, "", Bukkit.getOnlinePlayers().size() > 0
embed, 5, TimeUnit.SECONDS); ? (DPUtils
} catch (TimeoutException | InterruptedException e) { .sanitizeString(Bukkit.getOnlinePlayers().stream()
e.printStackTrace(); .map(Player::getDisplayName).collect(Collectors.joining(", ")))
} + (Bukkit.getOnlinePlayers().size() == 1 ? " was " : " were ")
}, ChannelconBroadcast.RESTART, false); + "kicked the hell out.") //TODO: Make configurable
ChromaBot.getInstance().updatePlayerList(); : "") //If 'restart' is disabled then this isn't shown even if joinleave is enabled
try { .build();
SafeMode = true; // Stop interacting with Discord MCChatUtils.forCustomAndAllMCChat(ch -> {
MCChatListener.stop(true); try {
ChromaBot.delete(); DiscordPlugin.sendMessageToChannelWait(ch, "",
dc.changePresence(StatusType.IDLE, ActivityType.PLAYING, "Chromacraft"); //No longer using the same account for testing embed, 5, TimeUnit.SECONDS);
dc.logout(); } catch (TimeoutException | InterruptedException e) {
mainServer = devServer = null; //Fetch servers and channels again e.printStackTrace();
sent = false; }
} catch (Exception e) { }, ChannelconBroadcast.RESTART, false);
TBMCCoreAPI.SendException("An error occured while disabling DiscordPlugin!", e); ChromaBot.getInstance().updatePlayerList();
} try {
} SafeMode = true; // Stop interacting with Discord
MCChatListener.stop(true);
private long lastannouncementtime = 0; ChromaBot.delete();
private long lastseentime = 0; dc.changePresence(StatusType.IDLE, ActivityType.PLAYING, "Chromacraft"); //No longer using the same account for testing
public static final ReactionEmoji DELIVERED_REACTION = ReactionEmoji.of(""); dc.logout();
mainServer = devServer = null; //Fetch servers and channels again
private void AnnouncementGetterThreadMethod() { sent = false;
while (!stop) { } catch (Exception e) {
try { TBMCCoreAPI.SendException("An error occured while disabling DiscordPlugin!", e);
if (SafeMode) { }
Thread.sleep(10000); }
continue;
} private long lastannouncementtime = 0;
String body = TBMCCoreAPI.DownloadString(SubredditURL + "/new/.json?limit=10"); private long lastseentime = 0;
JsonArray json = new JsonParser().parse(body).getAsJsonObject().get("data").getAsJsonObject() public static final ReactionEmoji DELIVERED_REACTION = ReactionEmoji.of("");
.get("children").getAsJsonArray();
StringBuilder msgsb = new StringBuilder(); private void AnnouncementGetterThreadMethod() {
StringBuilder modmsgsb = new StringBuilder(); while (!stop) {
long lastanntime = lastannouncementtime; try {
for (int i = json.size() - 1; i >= 0; i--) { if (SafeMode) {
JsonObject item = json.get(i).getAsJsonObject(); Thread.sleep(10000);
final JsonObject data = item.get("data").getAsJsonObject(); continue;
String author = data.get("author").getAsString(); }
JsonElement distinguishedjson = data.get("distinguished"); String body = TBMCCoreAPI.DownloadString(SubredditURL + "/new/.json?limit=10");
String distinguished; JsonArray json = new JsonParser().parse(body).getAsJsonObject().get("data").getAsJsonObject()
if (distinguishedjson.isJsonNull()) .get("children").getAsJsonArray();
distinguished = null; StringBuilder msgsb = new StringBuilder();
else StringBuilder modmsgsb = new StringBuilder();
distinguished = distinguishedjson.getAsString(); long lastanntime = lastannouncementtime;
String permalink = "https://www.reddit.com" + data.get("permalink").getAsString(); for (int i = json.size() - 1; i >= 0; i--) {
long date = data.get("created_utc").getAsLong(); JsonObject item = json.get(i).getAsJsonObject();
if (date > lastseentime) final JsonObject data = item.get("data").getAsJsonObject();
lastseentime = date; String author = data.get("author").getAsString();
else if (date > lastannouncementtime) { JsonElement distinguishedjson = data.get("distinguished");
do { String distinguished;
val reddituserclass = ChromaGamerBase.getTypeForFolder("reddit"); if (distinguishedjson.isJsonNull())
if (reddituserclass == null) distinguished = null;
break; else
val user = ChromaGamerBase.getUser(author, reddituserclass); distinguished = distinguishedjson.getAsString();
String id = user.getConnectedID(DiscordPlayer.class); String permalink = "https://www.reddit.com" + data.get("permalink").getAsString();
if (id != null) long date = data.get("created_utc").getAsLong();
author = "<@" + id + ">"; if (date > lastseentime)
} while (false); lastseentime = date;
if (!author.startsWith("<")) else if (date > lastannouncementtime) {
author = "/u/" + author; do {
(distinguished != null && distinguished.equals("moderator") ? modmsgsb : msgsb) val reddituserclass = ChromaGamerBase.getTypeForFolder("reddit");
.append("A new post was submitted to the subreddit by ").append(author).append("\n") if (reddituserclass == null)
.append(permalink).append("\n"); break;
lastanntime = date; val user = ChromaGamerBase.getUser(author, reddituserclass);
} String id = user.getConnectedID(DiscordPlayer.class);
} if (id != null)
if (msgsb.length() > 0) author = "<@" + id + ">";
genchannel.pin(sendMessageToChannelWait(genchannel, msgsb.toString())); } while (false);
if (modmsgsb.length() > 0) if (!author.startsWith("<"))
sendMessageToChannel(annchannel, modmsgsb.toString()); author = "/u/" + author;
if (lastannouncementtime != lastanntime) { (distinguished != null && distinguished.equals("moderator") ? modmsgsb : msgsb)
lastannouncementtime = lastanntime; // If sending succeeded .append("A new post was submitted to the subreddit by ").append(author).append("\n")
getConfig().set("lastannouncementtime", lastannouncementtime); .append(permalink).append("\n");
getConfig().set("lastseentime", lastseentime); lastanntime = date;
saveConfig(); }
} }
} catch (Exception e) { if (msgsb.length() > 0)
e.printStackTrace(); genchannel.pin(sendMessageToChannelWait(genchannel, msgsb.toString()));
} if (modmsgsb.length() > 0)
try { sendMessageToChannel(annchannel, modmsgsb.toString());
Thread.sleep(10000); if (lastannouncementtime != lastanntime) {
} catch (InterruptedException ex) { lastannouncementtime = lastanntime; // If sending succeeded
Thread.currentThread().interrupt(); getConfig().set("lastannouncementtime", lastannouncementtime);
} getConfig().set("lastseentime", lastseentime);
} saveConfig();
} }
} catch (Exception e) {
public static void sendMessageToChannel(IChannel channel, String message) { e.printStackTrace();
sendMessageToChannel(channel, message, null); }
} try {
Thread.sleep(10000);
public static void sendMessageToChannel(IChannel channel, String message, EmbedObject embed) { } catch (InterruptedException ex) {
try { Thread.currentThread().interrupt();
sendMessageToChannel(channel, message, embed, false); }
} catch (TimeoutException | InterruptedException e) { }
e.printStackTrace(); //Shouldn't happen, as we're not waiting on the result }
}
} public static void sendMessageToChannel(IChannel channel, String message) {
sendMessageToChannel(channel, message, null);
public static IMessage sendMessageToChannelWait(IChannel channel, String message) throws TimeoutException, InterruptedException { }
return sendMessageToChannelWait(channel, message, null);
} public static void sendMessageToChannel(IChannel channel, String message, EmbedObject embed) {
try {
public static IMessage sendMessageToChannelWait(IChannel channel, String message, EmbedObject embed) throws TimeoutException, InterruptedException { sendMessageToChannel(channel, message, embed, false);
return sendMessageToChannel(channel, message, embed, true); } catch (TimeoutException | InterruptedException e) {
} e.printStackTrace(); //Shouldn't happen, as we're not waiting on the result
}
public static IMessage sendMessageToChannelWait(IChannel channel, String message, EmbedObject embed, long timeout, TimeUnit unit) throws TimeoutException, InterruptedException { }
return sendMessageToChannel(channel, message, embed, true, timeout, unit);
} public static IMessage sendMessageToChannelWait(IChannel channel, String message) throws TimeoutException, InterruptedException {
return sendMessageToChannelWait(channel, message, null);
private static IMessage sendMessageToChannel(IChannel channel, String message, EmbedObject embed, boolean wait) throws TimeoutException, InterruptedException { }
return sendMessageToChannel(channel, message, embed, wait, -1, null);
} public static IMessage sendMessageToChannelWait(IChannel channel, String message, EmbedObject embed) throws TimeoutException, InterruptedException {
return sendMessageToChannel(channel, message, embed, true);
private static IMessage sendMessageToChannel(IChannel channel, String message, EmbedObject embed, boolean wait, long timeout, TimeUnit unit) throws TimeoutException, InterruptedException { }
if (message.length() > 1980) {
message = message.substring(0, 1980); public static IMessage sendMessageToChannelWait(IChannel channel, String message, EmbedObject embed, long timeout, TimeUnit unit) throws TimeoutException, InterruptedException {
Bukkit.getLogger() return sendMessageToChannel(channel, message, embed, true, timeout, unit);
.warning("Message was too long to send to discord and got truncated. In " + channel.getName()); }
}
try { private static IMessage sendMessageToChannel(IChannel channel, String message, EmbedObject embed, boolean wait) throws TimeoutException, InterruptedException {
MCChatUtils.resetLastMessage(channel); // If this is a chat message, it'll be set again return sendMessageToChannel(channel, message, embed, wait, -1, null);
final String content = message; }
RequestBuffer.IRequest<IMessage> r = () -> embed == null ? channel.sendMessage(content)
: channel.sendMessage(content, embed, false); private static IMessage sendMessageToChannel(IChannel channel, String message, EmbedObject embed, boolean wait, long timeout, TimeUnit unit) throws TimeoutException, InterruptedException {
if (wait) { if (message.length() > 1980) {
if (unit != null) message = message.substring(0, 1980);
return DPUtils.perform(r, timeout, unit); Bukkit.getLogger()
else .warning("Message was too long to send to discord and got truncated. In " + channel.getName());
return DPUtils.perform(r); }
} else { try {
if (unit != null) MCChatUtils.resetLastMessage(channel); // If this is a chat message, it'll be set again
plugin.getLogger().warning("Tried to set timeout for non-waiting call."); final String content = message;
else RequestBuffer.IRequest<IMessage> r = () -> embed == null ? channel.sendMessage(content)
DPUtils.performNoWait(r); : channel.sendMessage(content, embed, false);
return null; if (wait) {
} if (unit != null)
} catch (TimeoutException | InterruptedException e) { return DPUtils.perform(r, timeout, unit);
throw e; else
} catch (Exception e) { return DPUtils.perform(r);
Bukkit.getLogger().warning( } else {
"Failed to deliver message to Discord! Channel: " + channel.getName() + " Message: " + message); if (unit != null)
throw new RuntimeException(e); plugin.getLogger().warning("Tried to set timeout for non-waiting call.");
} else
} DPUtils.performNoWait(r);
return null;
public static Permission perms; }
} catch (TimeoutException | InterruptedException e) {
public boolean setupProviders() { throw e;
try { } catch (Exception e) {
Class.forName("net.milkbowl.vault.permission.Permission"); Bukkit.getLogger().warning(
Class.forName("net.milkbowl.vault.chat.Chat"); "Failed to deliver message to Discord! Channel: " + channel.getName() + " Message: " + message);
} catch (ClassNotFoundException e) { throw new RuntimeException(e);
return false; }
} }
RegisteredServiceProvider<Permission> permsProvider = Bukkit.getServer().getServicesManager() public static Permission perms;
.getRegistration(Permission.class);
perms = permsProvider.getProvider(); public boolean setupProviders() {
return perms != null; try {
} Class.forName("net.milkbowl.vault.permission.Permission");
} Class.forName("net.milkbowl.vault.chat.Chat");
} catch (ClassNotFoundException e) {
return false;
}
RegisteredServiceProvider<Permission> permsProvider = Bukkit.getServer().getServicesManager()
.getRegistration(Permission.class);
perms = permsProvider.getProvider();
return perms != null;
}
}

View file

@ -62,7 +62,7 @@ public abstract class DiscordSenderBase implements CommandSender {
(!broadcast && user != null ? user.mention() + "\n" : "") + msgtosend.trim()); (!broadcast && user != null ? user.mention() + "\n" : "") + msgtosend.trim());
sendtask = null; sendtask = null;
msgtosend = ""; msgtosend = "";
}, 10); // Waits a half second to gather all/most of the different messages }, 4); // Waits a 0.2 second to gather all/most of the different messages
} catch (Exception e) { } catch (Exception e) {
TBMCCoreAPI.SendException("An error occured while sending message to DiscordSender", e); TBMCCoreAPI.SendException("An error occured while sending message to DiscordSender", e);
} }

View file

@ -1,9 +1,6 @@
package buttondevteam.discordplugin.commands; package buttondevteam.discordplugin.commands;
import buttondevteam.discordplugin.ChannelconBroadcast; import buttondevteam.discordplugin.*;
import buttondevteam.discordplugin.DiscordConnectedPlayer;
import buttondevteam.discordplugin.DiscordPlayer;
import buttondevteam.discordplugin.DiscordPlugin;
import buttondevteam.discordplugin.mcchat.MCChatCustom; import buttondevteam.discordplugin.mcchat.MCChatCustom;
import buttondevteam.lib.chat.Channel; import buttondevteam.lib.chat.Channel;
import buttondevteam.lib.player.TBMCPlayer; import buttondevteam.lib.player.TBMCPlayer;
@ -75,7 +72,7 @@ public class ChannelconCommand extends DiscordCommandBase {
val dp = DiscordPlayer.getUser(message.getAuthor().getStringID(), DiscordPlayer.class); val dp = DiscordPlayer.getUser(message.getAuthor().getStringID(), DiscordPlayer.class);
val chp = dp.getAs(TBMCPlayer.class); val chp = dp.getAs(TBMCPlayer.class);
if (chp == null) { if (chp == null) {
message.reply("you need to connect your Minecraft account. On our server in #bot do /connect <MCname>"); message.reply("you need to connect your Minecraft account. On our server in " + DPUtils.botmention() + " do " + DiscordPlugin.getPrefix() + "connect <MCname>");
return true; return true;
} }
DiscordConnectedPlayer dcp = new DiscordConnectedPlayer(message.getAuthor(), message.getChannel(), chp.getUUID(), Bukkit.getOfflinePlayer(chp.getUUID()).getName()); DiscordConnectedPlayer dcp = new DiscordConnectedPlayer(message.getAuthor(), message.getChannel(), chp.getUUID(), Bukkit.getOfflinePlayer(chp.getUUID()).getName());
@ -100,12 +97,12 @@ public class ChannelconCommand extends DiscordCommandBase {
"---- Channel connect ---", // "---- Channel connect ---", //
"This command allows you to connect a Minecraft channel to a Discord channel (just like how the global chat is connected to #minecraft-chat).", // "This command allows you to connect a Minecraft channel to a Discord channel (just like how the global chat is connected to #minecraft-chat).", //
"You need to have access to the MC channel and have manage permissions on the Discord channel.", // "You need to have access to the MC channel and have manage permissions on the Discord channel.", //
"You also need to have your Minecraft account connected. In #bot use " + DiscordPlugin.getPrefix() + "connect <mcname>.", // "You also need to have your Minecraft account connected. In " + DPUtils.botmention() + " use " + DiscordPlugin.getPrefix() + "connect <mcname>.", //
"Call this command from the channel you want to use.", // "Call this command from the channel you want to use.", //
"Usage: @" + DiscordPlugin.dc.getOurUser().getName() + " channelcon <mcchannel>", // "Usage: @" + DiscordPlugin.dc.getOurUser().getName() + " channelcon <mcchannel>", //
"Use the ID (command) of the channel, for example `g` for the global chat.", // "Use the ID (command) of the channel, for example `g` for the global chat.", //
"To remove a connection use @ChromaBot channelcon remove in the channel.", // "To remove a connection use @ChromaBot channelcon remove in the channel.", //
"Mentioning the bot is needed in this case because the " + DiscordPlugin.getPrefix() + " prefix only works in #bot.", // "Mentioning the bot is needed in this case because the " + DiscordPlugin.getPrefix() + " prefix only works in " + DPUtils.botmention() + ".", //
"Invite link: <https://discordapp.com/oauth2/authorize?client_id=226443037893591041&scope=bot&permissions=268509264>" // "Invite link: <https://discordapp.com/oauth2/authorize?client_id=226443037893591041&scope=bot&permissions=268509264>" //
}; };
} }

View file

@ -32,11 +32,11 @@ public class FunModule extends Component {
}; };
private ConfigData<Boolean> serverReady() { private ConfigData<Boolean> serverReady() {
return getData("serverReady", true); return getConfig().getData("serverReady", true);
} }
private ConfigData<List<String>> serverReadyAnswers() { private ConfigData<List<String>> serverReadyAnswers() {
return getData("serverReadyAnswers", Arrays.asList(serverReadyStrings), return getConfig().getData("serverReadyAnswers", Arrays.asList(serverReadyStrings),
data -> (List<String>) data, data -> data); //TODO: Test data -> (List<String>) data, data -> data); //TODO: Test
} }

View file

@ -21,7 +21,7 @@ public class CommandListener {
if (!mentionedonly) { //mentionedonly conditions are in CommonListeners if (!mentionedonly) { //mentionedonly conditions are in CommonListeners
if (!message.getChannel().isPrivate() if (!message.getChannel().isPrivate()
&& !(message.getContent().charAt(0) == DiscordPlugin.getPrefix() && !(message.getContent().charAt(0) == DiscordPlugin.getPrefix()
&& channel.getStringID().equals(DiscordPlugin.botchannel.getStringID()))) // && channel.getStringID().equals(DiscordPlugin.plugin.CommandChannel().get().getStringID()))) //
return false; return false;
message.getChannel().setTypingStatus(true); // Fun message.getChannel().setTypingStatus(true); // Fun
} }

View file

@ -1,128 +1,128 @@
package buttondevteam.discordplugin.listeners; package buttondevteam.discordplugin.listeners;
import buttondevteam.discordplugin.DPUtils; import buttondevteam.discordplugin.DPUtils;
import buttondevteam.discordplugin.DiscordPlugin; import buttondevteam.discordplugin.DiscordPlugin;
import buttondevteam.discordplugin.mcchat.MinecraftChatModule; import buttondevteam.discordplugin.mcchat.MinecraftChatModule;
import buttondevteam.lib.architecture.Component; import buttondevteam.lib.architecture.Component;
import lombok.val; import lombok.val;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import sx.blah.discord.api.events.IListener; import sx.blah.discord.api.events.IListener;
import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent;
import sx.blah.discord.handle.impl.events.guild.role.RoleCreateEvent; import sx.blah.discord.handle.impl.events.guild.role.RoleCreateEvent;
import sx.blah.discord.handle.impl.events.guild.role.RoleDeleteEvent; import sx.blah.discord.handle.impl.events.guild.role.RoleDeleteEvent;
import sx.blah.discord.handle.impl.events.guild.role.RoleUpdateEvent; import sx.blah.discord.handle.impl.events.guild.role.RoleUpdateEvent;
import sx.blah.discord.handle.impl.events.user.PresenceUpdateEvent; import sx.blah.discord.handle.impl.events.user.PresenceUpdateEvent;
import sx.blah.discord.handle.obj.StatusType; import sx.blah.discord.handle.obj.StatusType;
import sx.blah.discord.util.EmbedBuilder; import sx.blah.discord.util.EmbedBuilder;
import java.util.Calendar; import java.util.Calendar;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class CommonListeners { public class CommonListeners {
/*private static ArrayList<Object> dcListeners=new ArrayList<>(); /*private static ArrayList<Object> dcListeners=new ArrayList<>();
public static void registerDiscordListener(DiscordListener listener) { public static void registerDiscordListener(DiscordListener listener) {
//Step 1: Get all events that are handled by us //Step 1: Get all events that are handled by us
//Step 2: Find methods that handle these //Step 2: Find methods that handle these
//...or just simply call the methods in the right order //...or just simply call the methods in the right order
} }
private static void callDiscordEvent(Event event) { private static void callDiscordEvent(Event event) {
String name=event.getClass().getSimpleName(); String name=event.getClass().getSimpleName();
name=Character.toLowerCase(name.charAt(0))+name.substring(1); name=Character.toLowerCase(name.charAt(0))+name.substring(1);
for (Object listener : dcListeners) { for (Object listener : dcListeners) {
listener.getClass().getMethods(name, AsyncDiscordEvent.class); listener.getClass().getMethods(name, AsyncDiscordEvent.class);
} }
}*/ }*/
private static long lasttime = 0; private static long lasttime = 0;
/* /*
MentionEvent: MentionEvent:
- CommandListener (starts with mention, only 'channelcon' and not in #bot) - CommandListener (starts with mention, only 'channelcon' and not in #bot)
MessageReceivedEvent: MessageReceivedEvent:
- v CommandListener (starts with mention, in #bot or a connected chat) - v CommandListener (starts with mention, in #bot or a connected chat)
- Minecraft chat (is enabled in the channel and message isn't [/]mcchat) - Minecraft chat (is enabled in the channel and message isn't [/]mcchat)
- CommandListener (with the correct prefix in #bot, or in private) - CommandListener (with the correct prefix in #bot, or in private)
*/ */
public static IListener<?>[] getListeners() { public static IListener<?>[] getListeners() {
return new IListener[]{new IListener<MessageReceivedEvent>() { return new IListener[]{new IListener<MessageReceivedEvent>() {
@Override @Override
public void handle(MessageReceivedEvent event) { public void handle(MessageReceivedEvent event) {
if (DiscordPlugin.SafeMode) if (DiscordPlugin.SafeMode)
return; return;
if (event.getMessage().getAuthor().isBot()) if (event.getMessage().getAuthor().isBot())
return; return;
boolean handled = false; boolean handled = false;
if (event.getChannel().getLongID() == DiscordPlugin.botchannel.getLongID() //If mentioned, that's higher than chat if (event.getChannel().getLongID() == DiscordPlugin.plugin.CommandChannel().get().getLongID() //If mentioned, that's higher than chat
|| event.getMessage().getContent().contains("channelcon")) //Only 'channelcon' is allowed in other channels || event.getMessage().getContent().contains("channelcon")) //Only 'channelcon' is allowed in other channels
handled = CommandListener.runCommand(event.getMessage(), true); //#bot is handled here handled = CommandListener.runCommand(event.getMessage(), true); //#bot is handled here
if (handled) return; if (handled) return;
val mcchat = Component.getComponents().get(MinecraftChatModule.class); val mcchat = Component.getComponents().get(MinecraftChatModule.class);
if (mcchat != null && mcchat.isEnabled()) //ComponentManager.isEnabled() searches the component again if (mcchat != null && mcchat.isEnabled()) //ComponentManager.isEnabled() searches the component again
handled = ((MinecraftChatModule) mcchat).getListener().handleDiscord(event); //Also runs Discord commands in chat channels handled = ((MinecraftChatModule) mcchat).getListener().handleDiscord(event); //Also runs Discord commands in chat channels
if (!handled) if (!handled)
handled = CommandListener.runCommand(event.getMessage(), false); handled = CommandListener.runCommand(event.getMessage(), false);
} }
}, new IListener<sx.blah.discord.handle.impl.events.user.PresenceUpdateEvent>() { }, new IListener<sx.blah.discord.handle.impl.events.user.PresenceUpdateEvent>() {
@Override @Override
public void handle(PresenceUpdateEvent event) { public void handle(PresenceUpdateEvent event) {
if (DiscordPlugin.SafeMode) if (DiscordPlugin.SafeMode)
return; return;
val devrole = DiscordPlugin.devServer.getRolesByName("Developer").get(0); val devrole = DiscordPlugin.devServer.getRolesByName("Developer").get(0);
if (event.getOldPresence().getStatus().equals(StatusType.OFFLINE) if (event.getOldPresence().getStatus().equals(StatusType.OFFLINE)
&& !event.getNewPresence().getStatus().equals(StatusType.OFFLINE) && !event.getNewPresence().getStatus().equals(StatusType.OFFLINE)
&& event.getUser().getRolesForGuild(DiscordPlugin.devServer).stream() && event.getUser().getRolesForGuild(DiscordPlugin.devServer).stream()
.anyMatch(r -> r.getLongID() == devrole.getLongID()) .anyMatch(r -> r.getLongID() == devrole.getLongID())
&& DiscordPlugin.devServer.getUsersByRole(devrole).stream() && DiscordPlugin.devServer.getUsersByRole(devrole).stream()
.noneMatch(u -> u.getPresence().getStatus().equals(StatusType.OFFLINE)) .noneMatch(u -> u.getPresence().getStatus().equals(StatusType.OFFLINE))
&& lasttime + 10 < TimeUnit.NANOSECONDS.toHours(System.nanoTime()) && lasttime + 10 < TimeUnit.NANOSECONDS.toHours(System.nanoTime())
&& Calendar.getInstance().get(Calendar.DAY_OF_MONTH) % 5 == 0) { && Calendar.getInstance().get(Calendar.DAY_OF_MONTH) % 5 == 0) {
DiscordPlugin.sendMessageToChannel(DiscordPlugin.devofficechannel, "Full house!", DiscordPlugin.sendMessageToChannel(DiscordPlugin.devofficechannel, "Full house!",
new EmbedBuilder() new EmbedBuilder()
.withImage( .withImage(
"https://cdn.discordapp.com/attachments/249295547263877121/249687682618359808/poker-hand-full-house-aces-kings-playing-cards-15553791.png") "https://cdn.discordapp.com/attachments/249295547263877121/249687682618359808/poker-hand-full-house-aces-kings-playing-cards-15553791.png")
.build()); .build());
lasttime = TimeUnit.NANOSECONDS.toHours(System.nanoTime()); lasttime = TimeUnit.NANOSECONDS.toHours(System.nanoTime());
} }
} }
}, (IListener<RoleCreateEvent>) event -> { }, (IListener<RoleCreateEvent>) event -> {
Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, () -> { 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 return; //Deleted or not a game role
DiscordPlugin.GameRoles.add(event.getRole().getName()); 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."); 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.");
}, 100); }, 100);
}, (IListener<RoleDeleteEvent>) event -> { }, (IListener<RoleDeleteEvent>) event -> {
if (DiscordPlugin.GameRoles.remove(event.getRole().getName())) if (DiscordPlugin.GameRoles.remove(event.getRole().getName()))
DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Removed " + event.getRole().getName() + " as a game role."); DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Removed " + event.getRole().getName() + " as a game role.");
}, (IListener<RoleUpdateEvent>) event -> { //Role update event }, (IListener<RoleUpdateEvent>) event -> { //Role update event
if (!DiscordPlugin.plugin.isGameRole(event.getNewRole())) { if (!DiscordPlugin.plugin.isGameRole(event.getNewRole())) {
if (DiscordPlugin.GameRoles.remove(event.getOldRole().getName())) if (DiscordPlugin.GameRoles.remove(event.getOldRole().getName()))
DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Removed " + event.getOldRole().getName() + " as a game role because it's color changed."); DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Removed " + event.getOldRole().getName() + " as a game role because it's color changed.");
} else { } else {
if (DiscordPlugin.GameRoles.contains(event.getOldRole().getName()) && event.getOldRole().getName().equals(event.getNewRole().getName())) if (DiscordPlugin.GameRoles.contains(event.getOldRole().getName()) && event.getOldRole().getName().equals(event.getNewRole().getName()))
return; return;
boolean removed = DiscordPlugin.GameRoles.remove(event.getOldRole().getName()); //Regardless of whether it was a game role boolean removed = DiscordPlugin.GameRoles.remove(event.getOldRole().getName()); //Regardless of whether it was a game role
DiscordPlugin.GameRoles.add(event.getNewRole().getName()); //Add it because it has no color DiscordPlugin.GameRoles.add(event.getNewRole().getName()); //Add it because it has no color
if (removed) if (removed)
DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Changed game role from " + event.getOldRole().getName() + " to " + event.getNewRole().getName() + "."); DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Changed game role from " + event.getOldRole().getName() + " to " + event.getNewRole().getName() + ".");
else else
DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Added " + event.getNewRole().getName() + " as game role because it has the default color."); DiscordPlugin.sendMessageToChannel(DiscordPlugin.modlogchannel, "Added " + event.getNewRole().getName() + " as game role because it has the default color.");
} }
}}; }};
} }
private static boolean debug = false; private static boolean debug = false;
public static void debug(String debug) { public static void debug(String debug) {
if (CommonListeners.debug) //Debug if (CommonListeners.debug) //Debug
DPUtils.getLogger().info(debug); DPUtils.getLogger().info(debug);
} }
public static boolean debug() { public static boolean debug() {
return debug = !debug; return debug = !debug;
} }
} }

View file

@ -313,7 +313,7 @@ public class MCChatListener implements Listener {
.collect(Collectors.joining(", ")) .collect(Collectors.joining(", "))
+ (user.getConnectedID(TBMCPlayer.class) == null + (user.getConnectedID(TBMCPlayer.class) == null
? "\nTo access your commands, first please connect your accounts, using /connect in " ? "\nTo access your commands, first please connect your accounts, using /connect in "
+ DiscordPlugin.botchannel.mention() + DPUtils.botmention()
+ "\nThen y" + "\nThen y"
: "\nY") : "\nY")
+ "ou can access all of your regular commands (even offline) in private chat: DM me `mcchat`!"); + "ou can access all of your regular commands (even offline) in private chat: DM me `mcchat`!");

View file

@ -1,43 +1,44 @@
package buttondevteam.discordplugin.mccommands; package buttondevteam.discordplugin.mccommands;
import buttondevteam.discordplugin.DiscordPlayer; import buttondevteam.discordplugin.DPUtils;
import buttondevteam.discordplugin.commands.ConnectCommand; import buttondevteam.discordplugin.DiscordPlayer;
import buttondevteam.discordplugin.mcchat.MCChatUtils; import buttondevteam.discordplugin.commands.ConnectCommand;
import buttondevteam.lib.chat.CommandClass; import buttondevteam.discordplugin.mcchat.MCChatUtils;
import buttondevteam.lib.player.ChromaGamerBase; import buttondevteam.lib.chat.CommandClass;
import buttondevteam.lib.player.TBMCPlayer; import buttondevteam.lib.player.ChromaGamerBase;
import buttondevteam.lib.player.TBMCPlayerBase; import buttondevteam.lib.player.TBMCPlayer;
import org.bukkit.entity.Player; import buttondevteam.lib.player.TBMCPlayerBase;
import org.bukkit.entity.Player;
@CommandClass(modOnly = false, path = "accept")
public class AcceptMCCommand extends DiscordMCCommandBase { @CommandClass(modOnly = false, path = "accept")
public class AcceptMCCommand extends DiscordMCCommandBase {
@Override
public String[] GetHelpText(String alias) { @Override
return new String[] { // public String[] GetHelpText(String alias) {
"§6---- Accept Discord connection ----", // return new String[] { //
"Accept a pending connection between your Discord and Minecraft account.", // "§6---- Accept Discord connection ----", //
"To start the connection process, do §b/connect <MCname>§r in the #bot channel on Discord", // "Accept a pending connection between your Discord and Minecraft account.", //
"Usage: /" + alias + " accept" // "To start the connection process, do §b/connect <MCname>§r in the " + DPUtils.botmention() + " channel on Discord", //
}; "Usage: /" + alias + " accept" //
} };
}
@Override
public boolean OnCommand(Player player, String alias, String[] args) { @Override
String did = ConnectCommand.WaitingToConnect.get(player.getName()); public boolean OnCommand(Player player, String alias, String[] args) {
if (did == null) { String did = ConnectCommand.WaitingToConnect.get(player.getName());
player.sendMessage("§cYou don't have a pending connection to Discord."); if (did == null) {
return true; player.sendMessage("§cYou don't have a pending connection to Discord.");
} return true;
DiscordPlayer dp = ChromaGamerBase.getUser(did, DiscordPlayer.class); }
TBMCPlayer mcp = TBMCPlayerBase.getPlayer(player.getUniqueId(), TBMCPlayer.class); DiscordPlayer dp = ChromaGamerBase.getUser(did, DiscordPlayer.class);
dp.connectWith(mcp); TBMCPlayer mcp = TBMCPlayerBase.getPlayer(player.getUniqueId(), TBMCPlayer.class);
dp.save(); dp.connectWith(mcp);
mcp.save(); dp.save();
ConnectCommand.WaitingToConnect.remove(player.getName()); mcp.save();
MCChatUtils.UnconnectedSenders.remove(did); //Remove all unconnected, will be recreated where needed ConnectCommand.WaitingToConnect.remove(player.getName());
player.sendMessage("§bAccounts connected."); MCChatUtils.UnconnectedSenders.remove(did); //Remove all unconnected, will be recreated where needed
return true; player.sendMessage("§bAccounts connected.");
} return true;
}
}
}

View file

@ -1,31 +1,32 @@
package buttondevteam.discordplugin.mccommands; package buttondevteam.discordplugin.mccommands;
import buttondevteam.discordplugin.commands.ConnectCommand; import buttondevteam.discordplugin.DPUtils;
import buttondevteam.lib.chat.CommandClass; import buttondevteam.discordplugin.commands.ConnectCommand;
import org.bukkit.entity.Player; import buttondevteam.lib.chat.CommandClass;
import org.bukkit.entity.Player;
@CommandClass(modOnly = false, path = "decline")
public class DeclineMCCommand extends DiscordMCCommandBase { @CommandClass(modOnly = false, path = "decline")
public class DeclineMCCommand extends DiscordMCCommandBase {
@Override
public String[] GetHelpText(String alias) { @Override
return new String[] { // public String[] GetHelpText(String alias) {
"§6---- Decline Discord connection ----", // return new String[] { //
"Decline a pending connection between your Discord and Minecraft account.", // "§6---- Decline Discord connection ----", //
"To start the connection process, do §b/connect <MCname>§r in the #bot channel on Discord", // "Decline a pending connection between your Discord and Minecraft account.", //
"Usage: /" + alias + " decline" // "To start the connection process, do §b/connect <MCname>§r in the " + DPUtils.botmention() + " channel on Discord", //
}; "Usage: /" + alias + " decline" //
} };
}
@Override
public boolean OnCommand(Player player, String alias, String[] args) { @Override
String did = ConnectCommand.WaitingToConnect.remove(player.getName()); public boolean OnCommand(Player player, String alias, String[] args) {
if (did == null) { String did = ConnectCommand.WaitingToConnect.remove(player.getName());
player.sendMessage("§cYou don't have a pending connection to Discord."); if (did == null) {
return true; player.sendMessage("§cYou don't have a pending connection to Discord.");
} return true;
player.sendMessage("§bPending connection declined."); }
return true; player.sendMessage("§bPending connection declined.");
} return true;
}
}
}