Skip to content

Developer API

Mathildeuh edited this page Sep 12, 2026 · 2 revisions

Developer API

Add SOS-Staff as a depend or softdepend in your own plugin.yml so it loads first, then fetch SosStaffAPI from Bukkit's ServicesManager once your plugin enables:

import fr.mathildeuh.sosstaff.api.SosStaffAPI;
import org.bukkit.Bukkit;

SosStaffAPI api = Bukkit.getServicesManager().getRegistration(SosStaffAPI.class).getProvider();

Reading tickets

Optional<Ticket> active = api.getActiveTicket(playerUuid);
List<Ticket> history = api.getTicketHistory(playerUuid);

Both are synchronous and read from an in-memory cache SOS-Staff keeps warm as players use the plugin - they never touch the database or block your thread. The tradeoff: a player who has an active ticket in the database but has triggered no SOS-Staff read or write yet this session (hasn't logged in or run a ticket command since the last restart) may not show up until they do. If you need a guaranteed-fresh answer immediately after server start, don't rely on this for players who haven't interacted with the plugin yet.

Creating a ticket

CompletableFuture<Ticket> future = api.createTicket(playerUuid, "bug", "Something is broken");

future.thenAccept(ticket -> {
    // created: real Discord channel, live-chat session, and all - identical to /ticket new
}).exceptionally(throwable -> {
    if (throwable.getCause() instanceof TicketCreationRejectedException rejected) {
        // cancelled by another plugin, too many open tickets, or still in the post-close cooldown
    }
    return null;
});

category must be a key from config.yml's categories section. This goes through the exact same pipeline as the in-game command, so a plugin-cancelled TicketCreateEvent (see below) or the anti-spam rules can both reject it - either way, the future completes exceptionally with a TicketCreationRejectedException (wrapped in a CompletionException/ExecutionException if you observe it via .join()/.get(), as usual for CompletableFuture).

Events

All four live in fr.mathildeuh.sosstaff.api.event, are synchronous (never fired from an async thread), and are Cancellable. Register a listener the normal Bukkit way:

@EventHandler
public void onTicketCreate(TicketCreateEvent event) {
    Ticket preview = event.getTicket(); // id() is 0 - nothing is persisted yet
    if (somethingIsWrong(preview)) {
        event.setCancelled(true); // the ticket is never created
    }
}
  • TicketCreateEvent - fires before a ticket is persisted. getTicket() is a transient preview (id() is 0, status() is always OPEN) - cancelling stops the creation entirely, before anything reaches the database or Discord.
  • TicketClaimEvent - fires before an existing ticket is marked claimed. getTicket() is the real, already-persisted ticket; getDiscordUserId() is the Discord snowflake of whoever's about to claim it - claiming is purely a Discord action and never requires a Minecraft account. Cancelling leaves it unclaimed.
  • TicketCloseEvent - fires before an existing ticket is closed. getReason() is the close reason about to be recorded. Cancelling leaves it open.
  • TicketMessageEvent - fires before a live-chat message is persisted and relayed, in either direction (isStaff() tells you which way). getAuthorUuid() is null for a message authored purely on the Discord side by someone with no resolvable Minecraft account. Cancelling drops the message: it is neither stored nor forwarded to the other side - useful for a chat filter.

Soft-depending on SOS-Staff

If your plugin should work with or without SOS-Staff installed, declare it under softdepend in your plugin.yml and check for the service before using it:

var registration = Bukkit.getServicesManager().getRegistration(SosStaffAPI.class);
if (registration != null) {
    SosStaffAPI api = registration.getProvider();
    // ...
}

Clone this wiki locally