Skip to content

API

DaisyFilter exposes a small, stable public API for other plugins. The API is registered through Bukkit’s ServicesManager.

DaisyFilterApi filter = Bukkit.getServicesManager()
.load(DaisyFilterApi.class);
FilterResult result = filter.scanPlain(actorId, FilterSurface.CUSTOM, text);
if (!result.isAllowed()) {
// react to result.getDisposition(), result.getSeverity(), etc.
}
interface DaisyFilterApi {
FilterResult scan(FilterInput input);
FilterResult scanPlain(UUID actorId, FilterSurface surface, String text);
boolean isAllowed(UUID actorId, FilterSurface surface, String text);
EngineStatus status();
}

scan is synchronous, thread-safe, and pure: it performs no logging, no spam-state mutation, no punishment, and no Bukkit side effects. It is safe to call from async chat threads. Inputs are bounded; custom API input is capped at 4,096 code points.

FilterInput, MessageContext, FilterSurface, NormalizedText, FilterDisposition, FilterAction, RuleMatch, HeuristicMatch, FilterResult, EngineStatus. Results are immutable and expose only safe metadata (masked previews and rule IDs), never stored raw content.

DaisyFilter does not currently fire Bukkit events. Earlier versions of this page listed DaisyFilterViolationEvent, DaisyFilterActionEvent, and DaisyFilterReloadEvent; none of them were ever implemented, and documenting them was a mistake.

To react to filtering today, call the registered service yourself — scan is pure and side-effect free, so you can run it against your own text without touching DaisyFilter’s state or recording an incident. If you need to observe DaisyFilter’s own decisions rather than make your own, open an issue describing the use case; an event surface is worth designing around a real consumer rather than guessing at one.

The engine never exposes mutable internals or global singleton state. Do not retain FilterResult spans to reconstruct blocked terms — censoring is one-way.