Made the plugin work cleanly (#51)
Clean install works pretty well Automatically setting first server as main server Removed devServer variable, getting the guild from the channels Disabling each component that doesn't have its channel(s)/role(s) set correctly (unless it's not required) Removed redundant variable from the FunModule Correctly handling missing channel settings in some places Checking any role position for game roles, not just "ChromaBot" The bot is playing Minecraft now Always giving permission for commands for now
This commit is contained in:
parent
14c42614d8
commit
cadb53d886
11 changed files with 104 additions and 51 deletions
|
@ -45,6 +45,7 @@ public class AnnouncerModule extends Component<DiscordPlugin> {
|
|||
|
||||
@Override
|
||||
protected void enable() {
|
||||
if (DPUtils.disableIfConfigError(this, channel(), modChannel())) return;
|
||||
stop = false; //If not the first time
|
||||
DPUtils.performNoWait(() -> {
|
||||
try {
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
package buttondevteam.discordplugin;
|
||||
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
import buttondevteam.lib.architecture.ConfigData;
|
||||
import buttondevteam.lib.architecture.IHaveConfig;
|
||||
import lombok.val;
|
||||
import org.bukkit.Bukkit;
|
||||
import sx.blah.discord.handle.obj.IChannel;
|
||||
import sx.blah.discord.handle.obj.IGuild;
|
||||
import sx.blah.discord.handle.obj.IIDLinkedObject;
|
||||
import sx.blah.discord.handle.obj.IRole;
|
||||
import sx.blah.discord.util.EmbedBuilder;
|
||||
|
@ -114,10 +117,14 @@ public final class DPUtils {
|
|||
}
|
||||
|
||||
public static ConfigData<IRole> roleData(IHaveConfig config, String key, String defName) {
|
||||
return roleData(config, key, defName, DiscordPlugin.mainServer);
|
||||
}
|
||||
|
||||
public static ConfigData<IRole> roleData(IHaveConfig config, String key, String defName, IGuild guild) {
|
||||
return config.getDataPrimDef(key, defName, name -> {
|
||||
val roles = DiscordPlugin.mainServer.getRolesByName((String) name);
|
||||
return roles.size() > 0 ? roles.get(0) : null; //TODO: May not handle null properly
|
||||
}, IIDLinkedObject::getLongID); //We can afford to search for the channel in the cache once (instead of using mainServer)
|
||||
val roles = guild.getRolesByName((String) name);
|
||||
return roles.size() > 0 ? roles.get(0) : null;
|
||||
}, IIDLinkedObject::getLongID);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -132,4 +139,32 @@ public final class DPUtils {
|
|||
return channel.mention();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the component if one of the given configs return null. Useful for channel/role configs.
|
||||
*
|
||||
* @param component The component to disable if needed
|
||||
* @param configs The configs to check for null
|
||||
* @return Whether the component got disabled and a warning logged
|
||||
*/
|
||||
public static boolean disableIfConfigError(@Nullable Component<DiscordPlugin> component, ConfigData<?>... configs) {
|
||||
for (val config : configs) {
|
||||
if (config.get() == null) {
|
||||
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);
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Failed to disable component after config error!", e);
|
||||
}
|
||||
getLogger().warning("The config value " + path + " isn't set correctly " + (component == null ? "in global settings!" : "for component " + component.getClass().getSimpleName() + "!"));
|
||||
getLogger().warning("Set the correct ID in the config" + (component == null ? "" : " or disable this component") + " to remove this message.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -108,7 +108,6 @@ public class DiscordPlugin extends ButtonPlugin implements IListener<ReadyEvent>
|
|||
}
|
||||
|
||||
public static IGuild mainServer;
|
||||
public static IGuild devServer;
|
||||
|
||||
private static volatile BukkitTask task;
|
||||
private static volatile boolean sent = false;
|
||||
|
@ -122,17 +121,22 @@ public class DiscordPlugin extends ButtonPlugin implements IListener<ReadyEvent>
|
|||
tries.incrementAndGet();
|
||||
if (tries.get() > 10) { //5 seconds
|
||||
task.cancel();
|
||||
getLogger().severe("Main or dev server not found! Set ID and do /discord reset");
|
||||
getLogger().severe("Main server not found! Invite the bot and do /discord reset");
|
||||
//getIConfig().getConfig().set("mainServer", 219529124321034241L); //Needed because it won't save as long as it's null - made it save
|
||||
saveConfig(); //Put default there
|
||||
return;
|
||||
}
|
||||
if (mainServer == null || devServer == null) {
|
||||
mainServer = event.getClient().getGuildByID(125813020357165056L);
|
||||
devServer = event.getClient().getGuildByID(219529124321034241L);
|
||||
mainServer = MainServer().get(); //Shouldn't change afterwards
|
||||
if (mainServer == null) {
|
||||
val guilds = dc.getGuilds();
|
||||
if (guilds.size() == 0)
|
||||
return; //If there are no guilds in cache, retry
|
||||
mainServer = guilds.get(0);
|
||||
getLogger().warning("Main server set to first one: " + mainServer.getName());
|
||||
MainServer().set(mainServer); //Save in config
|
||||
}
|
||||
if (mainServer == null || devServer == null)
|
||||
return; // Retry
|
||||
if (!TBMCCoreAPI.IsTestServer()) { //Don't change conditions here, see mainServer=devServer=null in onDisable()
|
||||
dc.changePresence(StatusType.ONLINE, ActivityType.PLAYING, "Chromacraft");
|
||||
dc.changePresence(StatusType.ONLINE, ActivityType.PLAYING, "Minecraft");
|
||||
} else {
|
||||
dc.changePresence(StatusType.ONLINE, ActivityType.PLAYING, "testing");
|
||||
}
|
||||
|
@ -140,6 +144,8 @@ public class DiscordPlugin extends ButtonPlugin implements IListener<ReadyEvent>
|
|||
if (task != null)
|
||||
task.cancel();
|
||||
if (!sent) {
|
||||
DPUtils.disableIfConfigError(null, CommandChannel(), ModRole()); //Won't disable, just prints the warning here
|
||||
|
||||
Component.registerComponent(this, new GeneralEventBroadcasterModule());
|
||||
Component.registerComponent(this, new MinecraftChatModule());
|
||||
Component.registerComponent(this, new ExceptionListenerModule());
|
||||
|
@ -242,7 +248,7 @@ public class DiscordPlugin extends ButtonPlugin implements IListener<ReadyEvent>
|
|||
ChromaBot.delete();
|
||||
dc.changePresence(StatusType.IDLE, ActivityType.PLAYING, "Chromacraft"); //No longer using the same account for testing
|
||||
dc.logout();
|
||||
mainServer = devServer = null; //Fetch servers and channels again
|
||||
//Configs are emptied so channels and servers are fetched again
|
||||
sent = false;
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("An error occured while disabling DiscordPlugin!", e);
|
||||
|
|
|
@ -11,6 +11,7 @@ public class Command2DC extends Command2<ICommand2DC, Command2DCSender> {
|
|||
|
||||
@Override
|
||||
public boolean hasPermission(Command2DCSender sender, ICommand2DC command) {
|
||||
return !command.isModOnly() || sender.getMessage().getAuthor().hasRole(DiscordPlugin.plugin.ModRole().get());
|
||||
//return !command.isModOnly() || sender.getMessage().getAuthor().hasRole(DiscordPlugin.plugin.ModRole().get()); //TODO: ModRole may be null; more customisable way?
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.bukkit.Bukkit;
|
|||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import sx.blah.discord.handle.obj.IChannel;
|
||||
import sx.blah.discord.handle.obj.IGuild;
|
||||
import sx.blah.discord.handle.obj.IRole;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -43,15 +44,14 @@ public class ExceptionListenerModule extends Component<DiscordPlugin> implements
|
|||
e.setHandled();
|
||||
}
|
||||
|
||||
private static IRole coderRole;
|
||||
|
||||
private static void SendException(Throwable e, String sourcemessage) {
|
||||
if (instance == null) return;
|
||||
try {
|
||||
if (coderRole == null)
|
||||
coderRole = DiscordPlugin.devServer.getRolesByName("Coder").get(0);
|
||||
IChannel channel = getChannel();
|
||||
assert channel != null;
|
||||
IRole coderRole = instance.pingRole(channel.getGuild()).get();
|
||||
StringBuilder sb = TBMCCoreAPI.IsTestServer() ? new StringBuilder()
|
||||
: new StringBuilder(coderRole.mention()).append("\n");
|
||||
: new StringBuilder(coderRole == null ? "" : coderRole.mention()).append("\n");
|
||||
sb.append(sourcemessage).append("\n");
|
||||
sb.append("```").append("\n");
|
||||
String stackTrace = Arrays.stream(ExceptionUtils.getStackTrace(e).split("\\n"))
|
||||
|
@ -61,7 +61,7 @@ public class ExceptionListenerModule extends Component<DiscordPlugin> implements
|
|||
stackTrace = stackTrace.substring(0, 1800);
|
||||
sb.append(stackTrace).append("\n");
|
||||
sb.append("```");
|
||||
DiscordPlugin.sendMessageToChannel(getChannel(), sb.toString()); //Instance isn't null here
|
||||
DiscordPlugin.sendMessageToChannel(channel, sb.toString()); //Instance isn't null here
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
@ -78,8 +78,13 @@ public class ExceptionListenerModule extends Component<DiscordPlugin> implements
|
|||
return DPUtils.channelData(getConfig(), "channel", 239519012529111040L);
|
||||
}
|
||||
|
||||
private ConfigData<IRole> pingRole(IGuild guild) {
|
||||
return DPUtils.roleData(getConfig(), "pingRole", "Coder", guild);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void enable() {
|
||||
if (DPUtils.disableIfConfigError(this, channel())) return;
|
||||
instance = this;
|
||||
Bukkit.getPluginManager().registerEvents(new ExceptionListenerModule(), getPlugin());
|
||||
TBMCCoreAPI.RegisterEventsForExceptions(new DebugMessageListener(), getPlugin());
|
||||
|
|
|
@ -13,10 +13,7 @@ import org.bukkit.event.EventHandler;
|
|||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import sx.blah.discord.handle.impl.events.user.PresenceUpdateEvent;
|
||||
import sx.blah.discord.handle.obj.IChannel;
|
||||
import sx.blah.discord.handle.obj.IMessage;
|
||||
import sx.blah.discord.handle.obj.IRole;
|
||||
import sx.blah.discord.handle.obj.StatusType;
|
||||
import sx.blah.discord.handle.obj.*;
|
||||
import sx.blah.discord.util.EmbedBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -27,8 +24,6 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.stream.IntStream;
|
||||
|
||||
public class FunModule extends Component<DiscordPlugin> implements Listener {
|
||||
private static FunModule mod;
|
||||
|
||||
private static final String[] serverReadyStrings = new String[]{"In one week from now", // Ali
|
||||
"Between now and the heat-death of the universe.", // Ghostise
|
||||
"Soon™", "Ask again this time next month", // Ghostise
|
||||
|
@ -68,7 +63,6 @@ public class FunModule extends Component<DiscordPlugin> implements Listener {
|
|||
|
||||
@Override
|
||||
protected void enable() {
|
||||
mod = this;
|
||||
registerListener(this);
|
||||
}
|
||||
|
||||
|
@ -99,7 +93,7 @@ public class FunModule extends Component<DiscordPlugin> implements Listener {
|
|||
return true; //Handled
|
||||
}
|
||||
lastlistp = (short) Bukkit.getOnlinePlayers().size(); //Didn't handle
|
||||
if (mod.serverReady().get()) {
|
||||
if (fm.serverReady().get()) {
|
||||
if (!TBMCCoreAPI.IsTestServer()
|
||||
&& Arrays.stream(serverReadyQuestions).anyMatch(msglowercased::contains)) {
|
||||
int next;
|
||||
|
@ -118,11 +112,8 @@ public class FunModule extends Component<DiscordPlugin> implements Listener {
|
|||
ListC = 0;
|
||||
}
|
||||
|
||||
private ConfigData<IRole> fullHouseDevRole() {
|
||||
return getConfig().getDataPrimDef("fullHouseDevRole", "Developer", name -> {
|
||||
val list = DiscordPlugin.devServer.getRolesByName((String) name);
|
||||
return list.size() > 0 ? list.get(0) : null;
|
||||
}, IRole::getName);
|
||||
private ConfigData<IRole> fullHouseDevRole(IGuild guild) {
|
||||
return DPUtils.roleData(getConfig(), "fullHouseDevRole", "Developer", guild);
|
||||
}
|
||||
|
||||
|
||||
|
@ -135,17 +126,19 @@ public class FunModule extends Component<DiscordPlugin> implements Listener {
|
|||
public static void handleFullHouse(PresenceUpdateEvent event) {
|
||||
val fm = ComponentManager.getIfEnabled(FunModule.class);
|
||||
if (fm == null) return;
|
||||
val devrole = fm.fullHouseDevRole().get();
|
||||
val channel = fm.fullHouseChannel().get();
|
||||
if (channel == null) return;
|
||||
val devrole = fm.fullHouseDevRole(channel.getGuild()).get();
|
||||
if (devrole == null) return;
|
||||
if (event.getOldPresence().getStatus().equals(StatusType.OFFLINE)
|
||||
&& !event.getNewPresence().getStatus().equals(StatusType.OFFLINE)
|
||||
&& event.getUser().getRolesForGuild(DiscordPlugin.devServer).stream()
|
||||
&& event.getUser().getRolesForGuild(channel.getGuild()).stream()
|
||||
.anyMatch(r -> r.getLongID() == devrole.getLongID())
|
||||
&& DiscordPlugin.devServer.getUsersByRole(devrole).stream()
|
||||
&& channel.getGuild().getUsersByRole(devrole).stream()
|
||||
.noneMatch(u -> u.getPresence().getStatus().equals(StatusType.OFFLINE))
|
||||
&& lasttime + 10 < TimeUnit.NANOSECONDS.toHours(System.nanoTime())
|
||||
&& Calendar.getInstance().get(Calendar.DAY_OF_MONTH) % 5 == 0) {
|
||||
DiscordPlugin.sendMessageToChannel(mod.fullHouseChannel().get(), "Full house!",
|
||||
DiscordPlugin.sendMessageToChannel(channel, "Full house!",
|
||||
new EmbedBuilder()
|
||||
.withImage(
|
||||
"https://cdn.discordapp.com/attachments/249295547263877121/249687682618359808/poker-hand-full-house-aces-kings-playing-cards-15553791.png")
|
||||
|
|
|
@ -38,7 +38,8 @@ public class CommonListeners {
|
|||
return;
|
||||
try {
|
||||
boolean handled = false;
|
||||
if (event.getChannel().getLongID() == DiscordPlugin.plugin.CommandChannel().get().getLongID() //If mentioned, that's higher than chat
|
||||
val commandChannel = DiscordPlugin.plugin.CommandChannel().get();
|
||||
if ((commandChannel != null && event.getChannel().getLongID() == commandChannel.getLongID()) //If mentioned, that's higher than chat
|
||||
|| event.getMessage().getContent().contains("channelcon")) //Only 'channelcon' is allowed in other channels
|
||||
handled = CommandListener.runCommand(event.getMessage(), true); //#bot is handled here
|
||||
if (handled) return;
|
||||
|
|
|
@ -144,7 +144,7 @@ public class ChannelconCommand extends ICommand2DC {
|
|||
"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.", //
|
||||
"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>" // TODO: Set correct client ID
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,6 +108,7 @@ class MCListener implements Listener {
|
|||
try {
|
||||
DPUtils.performNoWait(() -> {
|
||||
final IRole role = muteRole().get();
|
||||
if (role == null) return;
|
||||
final CommandSource source = e.getAffected().getSource();
|
||||
if (!source.isPlayer())
|
||||
return;
|
||||
|
@ -120,7 +121,11 @@ class MCListener implements Listener {
|
|||
user.addRole(role);
|
||||
else
|
||||
user.removeRole(role);
|
||||
DiscordPlugin.sendMessageToChannel(module.modlogChannel().get(), (e.getValue() ? "M" : "Unm") + "uted user: " + user.getName());
|
||||
val modlog = module.modlogChannel().get();
|
||||
String msg = (e.getValue() ? "M" : "Unm") + "uted user: " + user.getName();
|
||||
if (modlog != null)
|
||||
DiscordPlugin.sendMessageToChannel(modlog, msg);
|
||||
DPUtils.getLogger().info(msg);
|
||||
});
|
||||
} catch (DiscordException | MissingPermissionsException ex) {
|
||||
TBMCCoreAPI.SendException("Failed to give/take Muted role to player " + e.getAffected().getName() + "!",
|
||||
|
@ -143,7 +148,7 @@ class MCListener implements Listener {
|
|||
String name = event.getSender() instanceof Player ? ((Player) event.getSender()).getDisplayName()
|
||||
: event.getSender().getName();
|
||||
//Channel channel = ChromaGamerBase.getFromSender(event.getSender()).channel().get(); - TODO
|
||||
MCChatUtils.forAllMCChat(MCChatUtils.send(name + " <:YEEHAW:" + DiscordPlugin.mainServer.getEmojiByName("YEEHAW").getStringID() + ">s"));
|
||||
MCChatUtils.forAllMCChat(MCChatUtils.send(name + " <:YEEHAW:" + DiscordPlugin.mainServer.getEmojiByName("YEEHAW").getStringID() + ">s")); //TODO: Don't require emoji
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
|
|
|
@ -41,6 +41,7 @@ public class MinecraftChatModule extends Component<DiscordPlugin> {
|
|||
|
||||
@Override
|
||||
protected void enable() {
|
||||
if (DPUtils.disableIfConfigError(this, chatChannel())) return;
|
||||
listener = new MCChatListener(this);
|
||||
DiscordPlugin.dc.getDispatcher().registerListener(listener);
|
||||
TBMCCoreAPI.RegisterEventsForExceptions(listener, getPlugin());
|
||||
|
|
|
@ -40,30 +40,34 @@ public class GameRoleModule extends Component<DiscordPlugin> {
|
|||
val grm = ComponentManager.getIfEnabled(GameRoleModule.class);
|
||||
if (grm == null) return;
|
||||
val GameRoles = grm.GameRoles;
|
||||
val logChannel = grm.logChannel().get();
|
||||
if (roleEvent instanceof RoleCreateEvent) {
|
||||
Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, () -> {
|
||||
if (roleEvent.getRole().isDeleted() || !grm.isGameRole(roleEvent.getRole()))
|
||||
return; //Deleted or not a game role
|
||||
GameRoles.add(roleEvent.getRole().getName());
|
||||
DiscordPlugin.sendMessageToChannel(grm.logChannel().get(), "Added " + roleEvent.getRole().getName() + " as game role. If you don't want this, change the role's color from the default.");
|
||||
if (logChannel != null)
|
||||
DiscordPlugin.sendMessageToChannel(logChannel, "Added " + roleEvent.getRole().getName() + " as game role. If you don't want this, change the role's color from the default.");
|
||||
}, 100);
|
||||
} else if (roleEvent instanceof RoleDeleteEvent) {
|
||||
if (GameRoles.remove(roleEvent.getRole().getName()))
|
||||
DiscordPlugin.sendMessageToChannel(grm.logChannel().get(), "Removed " + roleEvent.getRole().getName() + " as a game role.");
|
||||
if (GameRoles.remove(roleEvent.getRole().getName()) && logChannel != null)
|
||||
DiscordPlugin.sendMessageToChannel(logChannel, "Removed " + roleEvent.getRole().getName() + " as a game role.");
|
||||
} else if (roleEvent instanceof RoleUpdateEvent) {
|
||||
val event = (RoleUpdateEvent) roleEvent;
|
||||
if (!grm.isGameRole(event.getNewRole())) {
|
||||
if (GameRoles.remove(event.getOldRole().getName()))
|
||||
DiscordPlugin.sendMessageToChannel(grm.logChannel().get(), "Removed " + event.getOldRole().getName() + " as a game role because it's color changed.");
|
||||
if (GameRoles.remove(event.getOldRole().getName()) && logChannel != null)
|
||||
DiscordPlugin.sendMessageToChannel(logChannel, "Removed " + event.getOldRole().getName() + " as a game role because it's color changed.");
|
||||
} else {
|
||||
if (GameRoles.contains(event.getOldRole().getName()) && event.getOldRole().getName().equals(event.getNewRole().getName()))
|
||||
return;
|
||||
boolean removed = GameRoles.remove(event.getOldRole().getName()); //Regardless of whether it was a game role
|
||||
GameRoles.add(event.getNewRole().getName()); //Add it because it has no color
|
||||
if (logChannel != null) {
|
||||
if (removed)
|
||||
DiscordPlugin.sendMessageToChannel(grm.logChannel().get(), "Changed game role from " + event.getOldRole().getName() + " to " + event.getNewRole().getName() + ".");
|
||||
DiscordPlugin.sendMessageToChannel(logChannel, "Changed game role from " + event.getOldRole().getName() + " to " + event.getNewRole().getName() + ".");
|
||||
else
|
||||
DiscordPlugin.sendMessageToChannel(grm.logChannel().get(), "Added " + event.getNewRole().getName() + " as game role because it has the default color.");
|
||||
DiscordPlugin.sendMessageToChannel(logChannel, "Added " + event.getNewRole().getName() + " as game role because it has the default color.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,6 +77,7 @@ public class GameRoleModule extends Component<DiscordPlugin> {
|
|||
return false; //Only allow on the main server
|
||||
val rc = new Color(149, 165, 166, 0);
|
||||
return r.getColor().equals(rc)
|
||||
&& r.getPosition() < DiscordPlugin.mainServer.getRoleByID(234343495735836672L).getPosition(); //Below the ChromaBot role
|
||||
&& DiscordPlugin.dc.getOurUser().getRolesForGuild(DiscordPlugin.mainServer)
|
||||
.stream().anyMatch(or -> r.getPosition() < or.getPosition()); //Below one of our roles
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue