Supporting clean installs, broadcast toggles, command improvements #92
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);
|
||||
}
|
||||
if (mainServer == null || devServer == null)
|
||||
return; // Retry
|
||||
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 (!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 (removed)
|
||||
DiscordPlugin.sendMessageToChannel(grm.logChannel().get(), "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.");
|
||||
if (logChannel != null) {
|
||||
if (removed)
|
||||
DiscordPlugin.sendMessageToChannel(logChannel, "Changed game role from " + event.getOldRole().getName() + " to " + event.getNewRole().getName() + ".");
|
||||
else
|
||||
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