Appearance
10. Discord Integration
AppelTools uses JDA 6.7.0 to post Discord embeds for significant events. Both Paper and Velocity modules ship a DiscordBot extending common/.../Discord/BaseDiscordBot. The Velocity module additionally provides StaffNotificationService for outbound staff notifications.
10.1 Bot Lifecycle
BaseDiscordBot (common)
java
public abstract class BaseDiscordBot {
protected JDA jda;
public abstract void start(String token, List<SlashCommandData> slashCommands);
public abstract void stop();
public boolean isConnected();
public JDA getJDA();
}Paper-side DiscordBot (paper/.../Discord/DiscordBot.java)
- Loaded only if
Modules.Discord.ROOT.isEnabled()and token is non-empty. - Hosts the
/searchslash command and Bukkit listeners filtered out of JDA.
Velocity-side DiscordBot (velocity/.../Discord/DiscordBot.java)
- Built with
litecommands-jdafor slash-command routing. - Hosts
StaffNotificationServiceand/search.
10.2 Embeds Factory (common/.../Discord/Embeds.java)
| Method | Color | Title | Used by |
|---|---|---|---|
createLogEmbed(String title, String description) | Green | varies | Periodic log messages. |
createMissingPluginsEmbed(List<String> missing) | Yellow | "Missing Plugins" | PluginChecker. |
createReportEmbed(Report report) | Red | "Report" | ReportCommand. |
createErrorEmbed(Throwable t) | Red | "Error" | Catch-all error logger. |
createWatchlistNoteEmbed(String player, String note) | Yellow | "Watch-list Note" | StaffNotesCommand. |
createCurseEmbed(String player, String message) | Orange | "Curse Word" | ChatListener / MessageCommand when curse detected. |
createStaffNotificationEmbed(StaffNotificationType type, String title, String description) | varies | varies | StaffNotificationService. |
createPunishmentEmbed(Punishment p) | Red | "Punishment" | All punishment commands. |
createStaffJoinEmbed(String name, String server) | Green | "Staff Join" | PlayerJoinListener if staff. |
createStaffLeaveEmbed(String name, String server) | Orange | "Staff Leave" | PlayerQuitListener if staff. |
createRestartEmbed(Duration remaining) | Orange | "Restart" | RestartServerCommand. |
createMaintenanceEmbed(boolean on) | Orange | "Maintenance" | MaintenanceCommand. |
createHelpEmbed() | Blue | "Help" | /search help. |
Each method returns net.dv8tion.jda.api.entities.MessageEmbed.
10.3 Staff Notification Types
java
public enum StaffNotificationType {
REPORT, // 📋
STAFF_JOIN, // 👤
STAFF_LEAVE, // 👤
PUNISHMENT, // ⚖️
MAINTENANCE, // 🔧
RESTART, // 🔄
MISSING_PLUGINS,// ⚠️
STAFF_NOTE, // 📝
FREEZE // ❄️
}StaffNotificationService exposes:
void sendReport(Report r)void sendStaffJoin(String name, String server)void sendStaffLeave(String name, String server)void sendPunishment(Punishment p)void sendMaintenance(boolean on)void sendRestart(Duration remaining)void sendMissingPlugins(List<String> plugins)void sendStaffNote(String player, String note)void sendFreeze(String target, String staff, boolean on)
Each method builds the embed, looks up the configured channel via Config.Discord.*_CHANNEL_ID, and posts with optional role pings from Config.Discord.PING_ROLE_IDS.
10.4 Slash Commands
/search <query>
- Cross-module search of recent log messages.
- Filters by
INFO/WARN/ERROR/DEBUGand text substring. - Returns an embed with up to 25 matching entries.
10.5 Configuration
Paper and Velocity both use the same config keys (defined in their respective Config.java):
| Key | Purpose |
|---|---|
modules.discord.root.enabled | Master switch. |
modules.discord.token | Bot token. |
discord.log_channel_id | Default log channel. |
discord.staff_channel_id | Staff-only events. |
discord.report_channel_id | Reports. |
discord.watchlist_channel_id | Staff notes. |
discord.ping_role_ids | List of role IDs to ping. |
discord.command_channel_id | Slash-command ack. |
discord.guild_id | Required for slash-command registration. |
10.6 Shadow Relocations
The Velocity shadowJar relocates net.dv8tion.jda to me.Maussee.AppelTools.libs.jda to avoid classpath conflicts on the proxy. Paper uses the libraries: block in paper-plugin.yml to load JDA as a runtime library (not relocated) because Paper plugins load via Paper's paper-plugin.yml and the system classloader.
10.7 Reliability
- If the bot is offline, every notification is dropped — they are not buffered to disk. The
PluginCheckerretries until the bot is online before posting the missing-plugins embed. - During
AppelToolsPaper.startup()andAppelToolsVelocity.onProxyInitialization(), the bot is started synchronously after DB setup; failure logs an error but does not abort startup.
10.8 Example
java
// In a punishment command:
plugin.getDiscordBot().ifPresent(bot -> {
Embeds.createPunishmentEmbed(punishment).ifPresent(embed -> {
TextChannel ch = bot.getJDA().getTextChannelById(
plugin.getConfig().getDiscord().getStaffChannelId());
if (ch != null) ch.sendMessageEmbeds(embed).queue();
});
});StaffNotificationService is a thin wrapper around this with role-ping injection.