# Customize Discord Templates

{% hint style="warning" %}
This functionality is only available from version 1.16.48 of the discord plugin
{% endhint %}

{% hint style="danger" %}
This is an advanced configuration section. A certain level of technical knowledge is required depending on how much you want to change.
{% endhint %}

## Introduction

To create your own custom discord messages you will need some knowledge of \
[The discord API](https://discord.com/developers/docs/resources/webhook#execute-webhook) and the [JEXL](https://commons.apache.org/proper/commons-jexl/) (Java Expression Language) [syntax](https://commons.apache.org/proper/commons-jexl/reference/syntax.html)\
\
Basically we are doing a REST call to the webhook URL and sending a JSON body with it.\
The JSON bodies are build from template files which can be found inside your **plugin directory** underneath a folder "**discordtemplates**". There are different template packs. **"default"** is enabled by default. Every [template pack](https://wiki.staffplusplus.org/master/integrations/discord-integration/template-packs) contains all the template files needed.

These files are a combination of JSON and JEXL.&#x20;

## Configuring a template

{% hint style="info" %}
To easily change and test templates, edit the template and execute the `/staffplusplusdiscord reload` command
{% endhint %}

Start by setting the "**updateTemplates**" property inside the **config.yml** file to **false**. This will prevent Staff++ Discord from overwriting the template files at startup.

Copy paste the **default** templates directory into a new directory with your template name:

![](https://292687455-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MPQohtcLxhXAvpSXOMt%2F-MVRMBBPkIxSQdGvzcS0%2F-MVRTaxDHyVAqWF1XZk9%2Ftemplates.png?alt=media\&token=749441d6-da7f-48f5-8e7e-8376f422dd42)

Change the **template** configuration property inside the **config.yml**

```yaml
StaffPlusPlusDiscord:
  templatePack: mycustomtemplates
```

S++ Discord will now start using the templates defined in the "**mycustomtemplates"** directory. Change these templates how you like. You can always switch back to another template pack by change the configuration property.

#### Example: discordtemplates/mycustomtemplates/reports/report-rejected.json

````javascript
// Context:
// report: IReport => https://github.com/garagepoort/StaffPlusPlus/blob/master/StaffPlusAPI/src/main/java/net/shortninja/staffplus/unordered/IReport.java
// timestamp: String
{
    "content": "Report update from Staff++",
    "embeds": [
        {
            "title": "Report rejected by ${report.staffName}",
            "url": "https://www.spigotmc.org/resources/staff.83562/",
            "color": "16601379",
            "timestamp": "${timestamp}",
            "footer": {
                "text": "Provided by Staff++",
                "icon_url": "https://cdn.discordapp.com/embed/avatars/0.png"
            },
            "fields": [
                {
                    "name": "Reporter",
                    "value": "${report.reporterName}\n[${report.reporterUuid}]",
                    "inline": true
                },
                {
                    "name": "Culprit",
                    "value": "${report.culpritUuid != null ? report.culpritName + '\\\\n[' + report.culpritUuid + ']' : '[Unknown]'}",
                    "inline": true
                },
                {
                    "name": "Staff",
                    "value": "${report.staffName}\n[${report.staffUuid}]",
                    "inline": false
                },
                {
                    "name": "Reason",
                    "value": "```${report.reason}```",
                    "inline": false
                },
                #IF report.closeReason != null
                {
                    "name": "Reason for closing",
                    "value": "```${report.closeReason}```",
                    "inline": false
                },
                #ENDIF
                {
                    "name": "Status",
                    "value": "**${report.reportStatus}**",
                    "inline": true
                },
                {
                    "name": "Location",
                    "value": "${report.location.isPresent() ? utils:parseLocation(report.serverName, report.location.get()) : 'Unknown'}",
                    "inline": true
                }
            ]
        }
    ]
}
````

The above shows the default template for a rejection of a report. This is a fairly good example because it contains most of what you might need. In theory you can completely overwrite the contents of this file as long as it will result in a valid JSON request body for the Discord Webhook API.

### JSON

Notice how most of the template is just a JSON body. The entirety of the body is constructed so it will be parsed into a valid request body that can be send to the discord webhook.\
I won't go into detail on the JSON structure because this is defined by the [Discord webhook API](https://discord.com/developers/docs/resources/webhook#execute-webhook).\
In the default templates I always use [Discord Embeds](https://discord.com/developers/docs/resources/channel#embed-object)

### JEXL

Before the above gets send to discord it gets parsed by the S++ Discord plugin.  It allows you to use JEXL expressions within the template.\
Everything inside the template between **"${}"** signs gets parsed as a JEXL expression.

**Context**

```javascript
// Context:
// report: IReport => https://github.com/garagepoort/StaffPlusPlus/blob/master/StaffPlusAPI/src/main/java/net/shortninja/staffplus/unordered/IReport.java
// timestamp: String
```

At the top of every template you will notice the context definition. This describes what properties are placed on the JEXL context for this template. A timestamp will always be provided.\
Besides, the timestamp you also get an object of type IReport. The type definition can be viewed on [Github](https://github.com/garagepoort/StaffPlusPlus/blob/master/StaffPlusAPI/src/main/java/net/shortninja/staffplus/unordered/IReport.java). Now that we know what properties we can access, we can write a JEXL expressions like this:

```javascript
"value": "${report.reporterName}\n[${report.reporterUuid}]"
```

In the above string literal we have 2 jexl expressions:

* ${report.reporterName}
* ${report.reporterUuid}

After the template is parsed and the Discord API is called your channel will receive a message looking like this:

![](https://292687455-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MPQohtcLxhXAvpSXOMt%2F-MTtzR6eLxf6hzGSP9Ir%2F-MTuHkrBz7eX2GKPPqwK%2Freject_report.png?alt=media\&token=708ae72f-6a54-430d-baa4-ac493ce99735)

## Conditional JSON

In the example template you will notice there is a section surrounded by an if statement.

````javascript
#IF report.closeReason != null
{
    "name": "Reason for closing",
    "value": "```${report.closeReason}```",
    "inline": false
},
#ENDIF
````

You can use the **#IF \<jexl expression> #ENDIF** syntax to allow certain parts of the JSON body to be in- or excluded. In this case only a closing reason section will be send to discord if there is actually a closing reason inside the IReport object.
