Skip to content

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 /search slash command and Bukkit listeners filtered out of JDA.

Velocity-side DiscordBot (velocity/.../Discord/DiscordBot.java) ​

  • Built with litecommands-jda for slash-command routing.
  • Hosts StaffNotificationService and /search.

10.2 Embeds Factory (common/.../Discord/Embeds.java) ​

MethodColorTitleUsed by
createLogEmbed(String title, String description)GreenvariesPeriodic 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)variesvariesStaffNotificationService.
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/DEBUG and 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):

KeyPurpose
modules.discord.root.enabledMaster switch.
modules.discord.tokenBot token.
discord.log_channel_idDefault log channel.
discord.staff_channel_idStaff-only events.
discord.report_channel_idReports.
discord.watchlist_channel_idStaff notes.
discord.ping_role_idsList of role IDs to ping.
discord.command_channel_idSlash-command ack.
discord.guild_idRequired 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 PluginChecker retries until the bot is online before posting the missing-plugins embed.
  • During AppelToolsPaper.startup() and AppelToolsVelocity.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.

Built with VitePress.