Customize Discord Templates

This functionality is only available from version 1.16.48 of the discord plugin

This is an advanced configuration section. A certain level of technical knowledge is required depending on how much you want to change.

Introduction

To create your own custom discord messages you will need some knowledge of The discord API and the JEXL (Java Expression Language) syntax 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 contains all the template files needed.

These files are a combination of JSON and JEXL.

Configuring a template

To easily change and test templates, edit the template and execute the /staffplusplusdiscord reload command

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:

Change the template configuration property inside the config.yml

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

// 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. In the default templates I always use Discord Embeds

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

// 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. Now that we know what properties we can access, we can write a JEXL expressions like this:

"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:

Conditional JSON

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

#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.

Last updated