---
url: https://docs.juniper.bot/en/message-templates/advanced/functions.md
description: Template Engine Global Functions
---

[server's dashboard]: ../../guide#configure

[Action]: ../../cmd/custom/actions/index

[Custom Commands]: ../../cmd/custom/index

# Functions

## Binary Functions { #binary }

### `defined`

The `defined` function is useful to check if a given expression is defined or not. It returns `true` if the given
expression is defined, `false` otherwise.

```template
{% if (defined([1, 2][5])) %}YES{% else %}NO{% endif %}
```

Previous example will output `NO` because index `5` of list `[1, 2]` is undefined.

### `even`

This function is quite simple, it is expecting one number as argument and it returns `true` when that number is even,
`false` otherwise.

```template
{% if (even(2)) %}A{% else %}B{% endif %}
```

Previous example prints `A`.

### `odd`

This is the opposite of the `even` function, it is expecting one number as argument and it returns `true` when that
number is odd, `false` otherwise.

```template
{% if (odd(2)) %}A{% else %}B{% endif %}
```

Previous example prints `B`.

### `iterable`

The `iterable` function allows to check if a given argument is a collection for loops can iterate over, or index/map selections can be used.

```template
{% if (iterable(2)) %}A{% else %}B{% endif %}
```

Previous template will print `B` because `2` is not a map or list so it is not iterable.

### `number`

The `number` function allows to check if a given argument is a number or available for automatic conversion to number
according to [Type Convert](../types/type-convert).

```template
{% if (number(2)) %}A{% else %}B{% endif %}
```

Previous template will print `A` because `2` is number.

### `empty`

The empty function returns a boolean value. As input it is expecting a generic object, it returns `true` if the given
input falls in one of the following scenarios:

* `null`
* `Undefined`
* empty list
* empty map
* zero number

```template
{% if (empty([1, 2])) %}A{% else %}B{% endif %}
```

Previous example produces `B` as `[1, 2]` is not an empty list.

## Math Functions { #math }

### `abs`

Mathematical function allowing to get the absolute value of an expression. For example,
`{{ abs(-1) }}` will produce `1`. It is expecting only one number argument.

### `round`

The round function allowing to round a given number to integer. An optional strategy can be specified as second argument:

* `'CEIL'` — round up;
* `'FLOOR'` — round down.

```template
{{ round(1.3, 'CEIL') }}
```

Previous example will produce `2`. Note that the strategy selection is case-insensitive, so one can either specify
`'CEIL'` or `'ceil'`. If the second argument is not specified half down will be applied.

## String Functions { #string }

### `number_format`

The `number_format` allowing to format a given number with specific symbols for the grouping and decimal separators,
also the number of fractional digits. This function expects at least one argument and can receive up to four arguments.
The list of arguments is presented below by the order they are expected:

1. The number to be formatted
2. The number of fractional digits (optional)
3. The decimal separator (optional)
4. The grouping separator (optional)

```template
{{ number_format(11000.136, 2, '.', ' ') }}
```

Previous example will produce `11 000.14`.

### `capitalize`

The capitalize function is expecting one argument and will capitalize the string.

```template
{{ capitalize('hello world') }}
```

Previous template will render as `Hello world` which is the result of capitalizing the first word.

### `format`

The `format` function receives an arbitrary number of arguments where the first is the template parameter (converted
to a String) and the remaining arguments is provided as the format model values.

```template
{{ format('hello %s! %s', 'world', 123) }}
```

Previous example will print `hello world! 123`.

### `lower`

Lowers the case of the string provided.

```template
{{ lower('JUNIPERBOT') }}
```

Previous example will print `juniperbot`.

### `upper`

Changes the case of the string provided by turning all into capitals.

```template
{{ upper('juniperbot') }}
```

Previous example will print `JUNIPERBOT`.

### `replace`

The `replace` function allows to specify a string and a map of replacements replacing all the occurrences of the keys in
the provided map by their respective value.

```template
{{ replace('Hello %name%', { '%name%': 'world' }) }}
```

Previous example will produce `Hello world` as output.

It can also accept a third boolean parameter that enables case-insensitive replace:

```template
{{ replace('Hello %NAME%', { '%name%': 'world' }, true) }}
```

Previous example will also produce `Hello world` as output despite the different case for search string.

### `split`

This function expects two arguments, using the second argument provided to split the first one into a collection.

```template
{{ split('juniper-bot', '-') }}
```

Previous example will return `[juniper, bot]`.

### `title`

The `title` function is expecting one string argument, capitalizing the first letter of all words present in it.

```template
{{ title('hello world') }}
```

Previous example will produce `Hello World`.

### `trim`

This function removes any whitespace characters from the beginning and/or ending of the given argument.

```template
{{ trim('  Hello World  ') }}
```

Previous example will produce `Hello World` without whitespaces.

### `startsWith`

This function checks if the first string argument starts with the second string argument.

```template
{{ startsWith('hello', 'he') }}
```

Previous example will produce `true` because `hello` starts with `he`.

It can also accept a third boolean parameter that enables case-insensitive check:

```template
{{ startsWith('HELLO', 'he', true) }}
```

Previous example will produce `true` because `HELLO` starts with `he` case-insensitive.

### `endsWith`

This function checks if the first string argument ends with the second string argument.

```template
{{ endsWith('hello', 'lo') }}
```

Previous example will produce `true` because `hello` ends with `lo`.

It can also accept a third boolean parameter that enables case-insensitive check:

```template
{{ endsWith('hello', 'LO', true) }}
```

Previous example will produce `true` because `hello` ends with `LO` case-insensitive.

### `contains`

This function checks if the first string argument contains the second string argument as substring.

```template
{{ contains('Hey there!', 'there') }}
```

Previous example will produce `true` because `Hey there!` contains substring `there`.

It's also possible to use a list of substrings, function will try to match any of them:

```template
{{ contains('Hey there!', ['there', 'heh']) }}
```

Previous example will produce `true` because `Hey there!` contains one of the specified substrings `there`.

It can also accept a third boolean parameter that enables case-insensitive check:

```template
{{ contains('Hey THERE!', 'there', true) }}
```

Previous example will produce `true` because `Hey THERE!` contains substring `there` case-insensitive.

### `plural`

This function will help you to choose the correct plural form of a word or phrase depending on the specified number and
language specified (cardinal numbers). The command accepts up to eight arguments, depending on the selected language.

First two arguments are number and language (`en` — English, `ru` — Russian). Others depends on language selected:

#### English

* Singular form
* Plural form

```template
2 {{ plural(2, 'en', 'day', 'days') }}
```

Previous example will produce `2 days`.

#### Russian

* Variation for 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001 (1 день, 51 день)
* Variation for 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002 (2 дня, 33 дня)
* Variation for 0, 5~19, 100, 1000, 10000, 100000, 1000000 (0 дней, 7 дней, 100 дней)
* General genitive case (1.5 дня)

```template
2 {{ plural(2, 'ru', 'день', 'дня', 'дней', 'дня') }}
```

Previous example will produce `2 дня`.

## Mixed Functions { #mixed }

### `random`

This function will return a random list element or number from the range specified.

```template
{{ random(['one', 'two', 'three']) }}
```

Previous example will produce `one`, `two` or `three` randomly.

In case of random list element, the list of weights for each element can be passed as second argument:

```template
{{ random(['one', 'two', 'three'], [10, 50, 40]) }}
```

Previous example will produce `one`, `two` or `three` randomly with 10%, 50%, 40% chance accordingly.

::: info
If weight is missing or invalid for specific element, it will be equal 0 that means this element will be excluded from selection.

But if all weights are missing or invalid, elements will be treated as equal (natural random element will be selected).
:::

Use range of numbers to get a random number:

```template
{{ random(10, 20) }}
```

Previous example will produce a random integer number from 10 to 20 inclusive.

If you specify only one number, the range from 0 to the specified number will be used:

```template
{{ random(10) }}
```

Previous example will produce a random integer number from 0 to 10 inclusive.

### `first`

The `first` function returns the first element of a collection or string. If the argument provided is not a collection
or a string, it will just return the input argument. If the given argument is an empty list or string, then it returns
`Undefined`.

```template
{{ first([1, 2]) }}
```

Previous example will produce `1`.

### `last`

The `last` function returns the last element of a collection or string. If the argument provided is not a collection or
a string, it will just return the input argument. If the given argument is an empty list or string, then it returns
`Undefined`.

```template
{{ last([1, 2]) }}
```

Previous example will produce `2`.

### `reverse`

The `reverse` function reverses the order of the elements in a given collection or string. If no collection neither
string is provided then it returns the given argument.

```template
{{ reverse([1, 2]) }}
```

Previous example will produce `[2, 1]`.

### `default`

The `default` function is expecting two arguments. It returns the second argument if the first argument is either `null` or `Undefined`.

```template
{{ default(null, 'Hello') }} {{ default(undefinedVariable, 'World') }}
```

Previous example will produce `Hello World`, because `undefinedVariable` is not defined.

### `length`

The `length` function returns the length of a given collection or string. If neither a collection or string is provided
then it returns `0` for both `null` and `Undefined`, otherwise `1` will be the result.

```template
{{ length([1, 2]) }}
{{ length(null) }}
{{ length(9) }}
```

Previous examples will print respectively `2`, `0` and `1`.

### `typeof`

The `typeof` function returns the [data type](../types/index) name for given value.

```template
{{ typeOf("blabla") }}
{{ typeOf(null) }}
{{ typeOf(9) }}
```

Previous examples will print respectively `String`, `null` and `Number`.

::: info
Please remember that template engine uses [automatic type conversion](../types/type-convert), so you shouldn't worry
about data types usually. This function can be useful for template debugging.
:::

## Lists and Maps { #lists-maps }

### `batch`

The `batch` function splits a given list in equally sized groups of items. It expects two arguments:

* A list as first argument;
* The second argument is the group size;

```template
{{ batch([1,2,3], 2) }}
```

### `concat` or `concatenate`

This function allows to concatenate a set of strings. It is expecting an arbitrary number of arguments (varargs).

```template
{{ concat('1', '+', '1', '=', '2') }}
```

Previous example will output `1+1=2`.

### `join`

The `join` function provides functionality somehow similar to the `concat` function, however they have some differences.
To start with, `join` takes only one or two arguments, where the first argument is expected to be a list and the second,
optional, argument a string to be used as the separator. If second argument is not specified, the comma with space is
used:  `,`.

```template
{{ join([1, null, 2], '|') }}
```

Previous example will print `1|2`. Note that, `join` function ignores `null` values.

### `keys`

The `keys` function can be used to expose the collection of keys for a given collection.

```template
{{ keys(['A', 'B']) }}
```

Previous example will produce `[0, 1]`.

### `values`

The `values` function can be used to expose the collection of values for a given collection.

```template
{{ values({'1':'one', '2':'two'}) }}
```

Previous example will produce `[one, two]`.

### `slice`

This function is expecting three arguments, where the first argument can either be a string or a collection, and an
integer as second and third arguments.

```template
{{ slice("123", 1, 1) }}
```

```template
{{ slice([1, 2, 3], 0, 2) }}
```

The second argument is the index position the slice will start from (inclusive), where the third argument is the
length of the slice. As shown in previous two examples, the result will be `"2"` and `[1, 2]` respectively. Note that,
slice is smart enough to handle boundary cases, for example:

```template
{{ slice("123", 2, 3) }}
```

```template
{{ slice("123", 5, 1) }}
```

Previous examples will still return a slice, depending on the number of characters or items provided in the first
argument, previous examples would then resolve the slice to `"3"` and `""`.

### `sort`

The `sort` function can be used to sort elements of a given collection. It accepts up to two arguments:

* Collection to sort;
* (Optional) Sort mode:
  * `ASC` - Sort in ascending order (default);
  * `DESC` - Sort in descending order;
  * `NUM_ASC` - Sort numbers in ascending order;
  * `NUM_DESC` - Sort numbers in ascending order.

```template
{{ sort(['2', '1', '10']) }}
```

Previous example will use `ASC` sort type (default if not specified) and will produce `[1, 10, 2]`.

You can notice that the sort order of previous example is weird, but that's because it sorts strings, not numbers.
This is the main difference between normal and `NUM_*` sort types. The normal `ASC`/`DESC` will sort collection elements
regardless of their data type, but the `NUM_ASC`/`NUM_DESC` will convert elements to numbers and will sort them.

Elements that can't be converted to number will be removed from the result:

```template
{{ sort(['2', '1', '10', 'NotANumber'], 'NUM_ASC') }}
```

Previous example will produce `[1, 2, 10]`.

### `shuffle`

The `shuffle` function will randomly shuffle the values of given list.

```template
{{ shuffle(['A', 'B', 'C', 'D']) }}
```

Previous example will print the list with randomly shuffled sequence of A, B, C, D.

## Date and Time { #datetime }

### `date`

The `date` function formats the date specified in the format you need. It accepts up to three arguments:

* Date object, timestamp or string `'now'` to format current date;
* (Optional) Date format based on Java `SimpleDateFormat`. Check [this](http://www.sdfonlinetester.info/) page for more details about the format;
* (Optional) Timezone in format of [TZ Database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). If not specified, the default server timezone is used. You can configure it in [server's dashboard];

```template
{{ date('now', 'EEE, d MMM yyyy HH:mm:ss z', 'Europe/Moscow') }}
```

Previous example will produce `Tue, 22 Jun 2021 04:04:05 MSK`.

### `calendar`

The `calendar` function creates a new [DateTime](../types/index#datetime) instance. It accepts up to two optional arguments:

1. Value that can be converted to date according to [type conversion](../types/type-convert#datetime):

   * String `'now'` to get current date;
   * Number as Unix timestamp;
   * Date string in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format.

   If this value is not specified, the current date will be used.
2. Timezone in format of [TZ Database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). If no timezone specified, the default server timezone is used. You can configure it in [server's dashboard].

```template
{{ calendar('now', 'Europe/Moscow') }}
```

Previous example will produce `Tue, 22 Jun 2021 04:04:05 MSK`.

As this is [DateTime](../types/index#datetime) instance, you can use all its functionality like this:

```template
{% set currentDate = calendar('now', 'Europe/Moscow') %}
{% set fiveHours = currentDate.plusHours(5) %}
{{ currentDate }}
{{ fiveHours }}
```

Previous example will produce two dates with 5-hours difference:

```template
Tue, 22 Jun 2021 04:04:05 MSK
Tue, 22 Jun 2021 09:04:05 MSK
```

### `duration`

The `duration` function formats the specified time interval to readable time format. It accepts up to two arguments:

* Interval (milliseconds);
* (Optional) Maximum amount of units. Default is 2.

```template
{{ duration(3650, 2) }}
```

Previous example will produce `3 sec, 650 ms`.

## Interactions { #interactions }

### `reaction`

The `reaction` function will add a reaction with the specified emotion to resulting message. It accepts one argument of emotion in the following formats:

* `🦊` — Unicode-character;
* `:fox_face:` — name of emotion including default and server's emojis;
* `<a:foxwaggy:695917473874051112>` — custom emoji code.

```template
{% do reaction(':fox_face:') %}
```

::: tip
Only one reaction can be added to the message. Servers with [active Bonus](https://juniper.bot/donate) can add up to 5 reactions.
:::

## Message Components { #message-components }

### `button`

The `button` function will add a specified button to resulting message. It accepts six string arguments.

* The first argument is the button style:
  * `LINK` — Link button style, usually in gray and has a link attached;
  * `PRIMARY` — Primary button style, usually in blue. Often used as the accept, submit, or acknowledge button;
  * `SECONDARY` — Secondary button style, usually in gray. Often used as the cancel or lesser used option;
  * `SUCCESS` — Success/Approve button style, usually in green. This should be used to indicate a positive action;
  * `DANGER` — Danger/Deny button style, usually in red. This button should be used to indicate destructive actions;
* The second argument is URL for link button or identifier for other button types;
* The third argument is button label;
* The fourth argument is emoji (Optional, can be `null`);
* The fifth argument is UUID of [Action] to execute (required for all button styles except link button);
* The sixth optional argument is boolean flag if this button must be disabled.

```template
{% do button('LINK', 'https://juniper.bot/', 'Website', '🦊') %}
{% do button('PRIMARY', 'acceptBtn', 'Accept', '✅', 'b39297ea-cc2d-4f88-a475-d4a9df94cb99') %}
{% do button('PRIMARY', 'acceptBtn', 'Accept (Disabled)', '✅', 'b39297ea-cc2d-4f88-a475-d4a9df94cb99', true) %}
```

::: warning
Buttons performing [Action], that is all button styles except link buttons, are **only available for [Custom Commands]**.
:::

### `select_menu`

The `select_menu` function will add a selection menu to resulting message. It accepts five string arguments.

* The first argument is the menu type:
  * `STRING` — String Selection Menu;
  * `USER` — User Selection Menu;
  * `ROLE` — Role Selection Menu;
  * `MENTIONABLE` — User\&Role Selection Menu;
  * `CHANNEL` — Channel Selection Menu;
* The second argument is identifier;
* The third argument is placeholder text if nothing is specified;
* The fourth argument is UUID of [Action] to execute;
* The fifth optional argument is boolean flag if this menu must be disabled.

```template
{% do select_menu('CHANNEL', 'selectedChannels', 'Select Channels', 'b39297ea-cc2d-4f88-a475-d4a9df94cb99')
      .withMinValues(2)
      .withMaxValues(3)
      .withChannelTypes(['VOICE', 'TEXT']) %}

{% do select_menu('STRING', 'selectedSpecies', 'Who are you?', 'b39297ea-cc2d-4f88-a475-d4a9df94cb99')
      .addOption('Otter', 'otterOption', ':otter:')
      .addOption('Fox', 'foxOption', ':fox_face:')
      .withDefaultOption('foxOption') %}

{% do select_menu('MENTIONABLE', 'selectedEntry', 'Select role or member', 'b39297ea-cc2d-4f88-a475-d4a9df94cb99', true)
      .withDefaultOptions(['310848622642069504']) %}
```

::: tip
This function is only available for servers with [bonus](https://juniper.bot/donate)!
:::

::: warning
Menus are **only available for [Custom Commands]**
:::

### `components_row`

The `components_row` function will add new message components row for all following executions of [button](#button) function.
