# Custom Chat Integration

Verité normally filters messages automatically. However, some chat plugins intercept Minecraft's normal chat event and handle message delivery themselves.

If your plugin does this, Verité may never receive the original message to filter. In that case, you should pass the message through Verité before your plugin sends it.

> **You only need this guide if your plugin handles or replaces normal Minecraft chat.** Servers using standard chat do not need any additional setup.

## Java Integration

Verité provides a small public API specifically for integrations like custom chat systems.

### 1. Add Verité as a soft dependency

Add Verité to your `plugin.yml`:

```yaml
softdepend:
  - Verite
```

Using a soft dependency ensures Verité loads before your integration when installed, without making it mandatory for your plugin to start.

### 2. Check whether the API is available

If Verité is optional, check for the API before using it:

```java
private static final boolean VERITE_AVAILABLE;

static {
    boolean available;

    try {
        Class.forName("teacommontea.api.VeriteFilter");
        available = true;
    } catch (ClassNotFoundException ignored) {
        available = false;
    }

    VERITE_AVAILABLE = available;
}
```

Your integration can then simply do nothing when Verité isn't installed.

### 3. Filter the message

Before your custom chat system sends a message, pass it to `VeriteFilter`:

```java
if (VERITE_AVAILABLE) {
    FilterResult result = VeriteFilter.check(
        player.getUniqueId(),
        message
    );

    if (result.blocks()) {
        player.sendMessage(VeriteFilter.blockMessage());
        return;
    }
}
```

That's all that is required for a basic integration.

`check()` runs the message through Verité's filter and records the flag against the player. If `.blocks()` returns `true`, your chat system should prevent the message from being sent.

### Using the filter category

Sometimes you'll want to know **why** Verité caught a message:

```java
FilterResult result = VeriteFilter.check(
    player.getUniqueId(),
    message
);

switch (result) {
    case CLEAN -> {
        // Send normally
    }

    case SELF_HARM, ABUSE -> {
        // Handle appropriately
    }

    default -> {
        // Ordinary blocked content
    }
}
```

The possible results are:

* `CLEAN`
* `BLOCK`
* `PROFANITY`
* `SELF_HARM`
* `ABUSE`

Anything except `CLEAN` returns `true` from `.blocks()`.

> **Important:** `SELF_HARM` and `ABUSE` exist so these messages can be handled differently from ordinary rule violations. We recommend against automatically treating them as punishable chat offenses.

### Detecting repeated messages

If your chat system needs to distinguish filtered content from repeat-message detection, use the repeat-aware overload:

```java
FilterOutcome outcome = VeriteFilter.check(
    player.getUniqueId(),
    message,
    true
);

if (outcome.blocks()) {
    if (outcome.repeat()) {
        player.sendMessage(VeriteFilter.repeatMessage());
    } else {
        player.sendMessage(VeriteFilter.blockMessage());
    }

    return;
}
```

`outcome.category()` provides the normal filter category, while `outcome.repeat()` tells you whether the message was blocked because it was repeated.

## Filtering Other User Content

The API isn't limited to chat.

If your plugin accepts user-written content such as nicknames, prefixes, team tags, or similar fields, you can run those through the same filter:

```java
if (VeriteFilter.check(player.getUniqueId(), nickname).blocks()) {
    // Reject the nickname
}
```

For text that doesn't belong to a particular player, use `VeriteFilter.ANONYMOUS`:

```java
FilterResult result = VeriteFilter.check(
    VeriteFilter.ANONYMOUS,
    text
);
```

Anonymous checks still return the appropriate filter category, but do not add a flag to any player's record.

---

# Using Verité with Skript

If your custom chat system is written in Skript, you don't need to interact with the Java API.

With **Verité and Skript installed**, Verité's filtering syntax is available automatically.

## Filtering Custom Chat

If your script already handles sending chat messages itself, check the message before sending it:

```vb
if {_msg} is blocked for player:
    send block message to player
    stop
```

Including `for player` tells Verité who sent the message and records the flag against that player.

Without a player:

```vb
if {_text} is blocked:
    # Reject the text
```

Verité performs a pure filter check without recording a flag. This is useful for things such as names, tags, signs, or other text that shouldn't count against a specific player.

## Checking Why a Message Was Blocked

For more control, retrieve the filter result:

```vb
set {_result} to filter result of {_msg} for player

if {_result} is "self_harm":
    # Handle separately
    stop

if {_result} is "abuse":
    # Handle separately
    stop

if {_result} is not "clean":
    send block message to player
    stop
```

The result will be one of:

`clean`, `block`, `profanity`, `self_harm`, or `abuse`

> **Important:** Consider handling `self_harm` and `abuse` separately from ordinary moderation violations rather than automatically punishing the player.

## Checking a Player's Flag Count

You can also retrieve the number of messages Verité has flagged for a player:

```vb
set {_flags} to message flags of player
```

This can be used by your own moderation system if you want different behaviour for repeated violations.

## Skript Syntax Reference

```vb
%string% is blocked [for %-player%]
%string% is not blocked [for %-player%]

filter result of %string% [for %-player%]

block message

message flags of %player%
```

The optional player matters:

**With a player:** the filter result is recorded against that player.

**Without a player:** Verité only checks the text and does not record a flag.

---

## API Reference

The public API is located under:

```text
teacommontea.api
```

The primary class for chat integrations is:

```java
VeriteFilter
```

Useful methods include:

```java
VeriteFilter.check(UUID player, String message)
VeriteFilter.check(UUID player, String message, boolean repeatAware)

VeriteFilter.count(UUID player)

VeriteFilter.blockMessage()
VeriteFilter.repeatMessage()
VeriteFilter.selfHarmMessage()

VeriteFilter.blockNotice(FilterResult result, String message)
```

`VeriteFilter.ANONYMOUS` can be used when filtering text that isn't associated with a player.

Verité also exposes its normalization utilities for integrations that need them, including accent folding, entity stripping, repeated-character reduction, fingerprinting, and edge trimming. These functions are thread-safe and generally **do not need to be called manually** before using `check()`.

For most custom chat integrations, all you need is:

```java
if (VeriteFilter.check(player.getUniqueId(), message).blocks()) {
    // Don't send the message
}
```

Verité handles the rest.
