All available data that can be used in YAGPDB's templating "engine" which is slightly modified version of Golang's stdlib text/template package; more in depth and info about actions, pipelines and global functions like printf, index, len,
etc > https://golang.org/pkg/text/template/ . This section is meant to be a concise and to the point reference document for all available templates/functions. For detailed explanations and syntax guide refer to the learning resource.
Legend: at current state this is still prone to formatting errors, but everything in a code block
should refer to a function, parts of a template's action-structure or output returned by YAGPDB; single word/literal-structure in italics refers to type. Methods and fields (e.g. .Append, .User) are usually kept in standard formatting. If argument for a function is optional, it's enclosed in parenthesis ( )
. If there are many optional arguments possible, it's usually denoted by 3-dot ...
ellipsis.
If functions or methods are denoted with an accent, tilde ~, they are not yet deployed in actual YAGPDB bot but are already in master code branch.
Always put curly brackets around the data and "actions you perform" you want to formulate as a template's action-structure like this: {{.User.Username}}
This {{ ... }}
syntax of having two curly brackets aka braces around context is always necessary to form a template's control structure aka an action with methods and functions stated below.
Templating system uses standard ASCII quotation marks:
0x22 > "
for straight double quotes, 0x27 > '
for apostrophes and 0x60 `
for backticks;
so make sure no "smart-quotes" are being used.
The dot (also known as cursor) {{ . }}
encompasses all active data available for use in the templating system, in other words it always refers to current context.
From official docs > "Execution of the template walks the structure and sets the cursor, represented by a period .
and called "dot", to the value at the current location in the structure as execution proceeds." All following fields/methods/objects like User/Guild/Member/Channel etc are all part of that dot-structure and there are some more in tables below.
$
has a special significance in templates, it is set to the starting value of a dot. This means you have access to the global context from anywhere - e.g., inside range
/with
actions. $
for global context would cease to work if you redefine it inside template, to recover it {{ $ := . }}
.
$
also denotes the beginning of a variable, which maybe be initialized inside a template action. So data passed around template pipeline can be initialized using syntax > $variable := value
. Previously declared variable can also be assigned with new data > $variable = value
, it has to have a white-space before it or control panel will error out. Variable scope extends to the end
action of the control structure (if
, with
, or range
) in which it is declared, or to the end of custom command if there are no control structures - call it global scope.
Field | Description |
.CCID | The ID of currently executing custom command in type of int64. |
.IsPremium | Returns boolean true/false whether guild is premium of YAGPDB or not. |
.CCRunCount | Shows run count of triggered custom command, although this is not going to be 100% accurate as it's cached up to 30 minutes. |
A powerful component of templates is the ability to stack actions - like function calls, together - chaining one after another. This is done by using pipes |
. Borrowed from Unix pipes, the concept is simple: each pipeline’s output becomes the input of the following pipe. One limitation of the pipes is that they can only work with a single value and that value becomes the last parameter of the next pipeline.
Example: {{randInt 41 | add 2}}
would pipelinerandInt
function's return to addition add
as second parameter and it would be added to 2; this more simplified would be like {{40 | add 2}}
with return 42. If written normally, it would be {{ add 2 (randInt 41) }}
. Same pipeline but using a variable is also useful one -{{$x:=40 | add 2}}
would not return anything as printout, 40 still goes through pipeline to addition and 42 is stored to variable $x
.
Pipes are useful in select cases to shorten code and in some cases improve readability, but they should not be overused. In most cases, pipes are unnecessary and cause a dip in readability that helps nobody.
Field | Description |
.User | The user's username together with discriminator. |
.User.String | The user's username together with discriminator as string type. |
.User.Username | The user's username. |
.User.ID | The user's ID. |
.User.Discriminator | The user's discriminator (The four digits after a person's username). |
.User.Avatar | The user's avatar ID. |
.User.AvatarURL "256" | Gives the URL for user's avatar, argument "256" is the size of the picture and can increase/decrease twofold (e.g. 512, 1024 or 128, 64 etc.). |
.User.Bot | Determines whether the target user is a bot - if yes, it will return True. |
.User.Mention | Mentions user. |
.RealUsername | Only works with join and leave messages (not join dms). This can be used to send the real username to a staff channel when invites are censored. |
.UsernameHasInvite | Only works with join and leave messages (not join dms). It will determine does the username contain an invite link. |
Function | Description |
| Function that can be used to retrieve .User object from a mention or userID.
|
| Returns a slice of type [ ]*logs.CCNameChange having fields .Name and .Time of previous 15 usernames and skips
|
| Same as |
User object in Discord documentation.
{{(userArg .Guild.OwnerID).String}}
this template's action-structure returns Guild/Server owner's username and discriminator as of type string. First, userArg
function is given .Guild.OwnerID
as argument (what it does, explained below). The parentheses surrounding them make userArg
function return .User
as .User object which is handled further by .String
method (ref..User.String
), giving a result like > YAGPDB#8760
.
Field | Description |
.Guild.ID | Outputs the ID of the guild. |
.Guild.Name | Outputs the name of the guild. |
.Guild.Icon | Outputs the icon hash ID of the guild's icon. |
.Guild.Splash | Outputs the splash hash ID of the guild's splash. |
.Guild.Region | Outputs the region of the guild. |
.Guild.AfkChannelID | Outputs the AFK channel ID. |
.Guild.OwnerID | Outputs the ID of the owner. |
.Guild.JoinedAt | Outputs the timestamp when YAGPDB joined the guild. To convert it to type time.Time, use .Parse method > |
.Guild.AfkTimeout | Outputs the time when a user gets moved into the AFK channel while not being active. |
.Guild.MemberCount | Outputs the number of users on a guild. |
.Guild.VerificationLevel | Outputs the required verification level for the guild. |
.Guild.ExplicitContentFilter | Outputs the explicit content filter level for the guild. |
.Guild.DefaultMessageNotifications | Outputs the default message notification setting for the guild. |
.Guild.VoiceStates | Outputs a list of voice states (users connected to VCs) with type *discordgo.VoiceState. |
.Guild.EmbedEnabled | Outputs whether guild is embeddable (e.g. widget) or not, true / false. |
.Guild.SystemChannelID | The id of the channel where guild notices such as welcome messages and boost events are posted. |
.Guild.MfaLevel | required MFA level for the guild. If enabled, members with moderation powers will be required to have 2-factor authentication enabled in order to exercise moderation powers. |
.Guild.Roles | Outputs all roles and indexing them gives more information about the role. For example |
.Guild.WidgetEnabled | Outputs whether or not the Server Widget is enabled or not. |
.Guild.WidgetChannelID | Outputs the channel id for the server widget. |
Guild object in Discord documentation.
Field | Description |
.Member.JoinedAt | When member joined the guild/server of type discordgo.Timestamp. Method .Parse will convert this to of type time.Time. |
.Member.Nick | The nickname for this member. |
.Member.Roles | A slice of role IDs that the member has. |
.Member.User | Underlying user on which the member is based on. |
Function | Description |
| Edits triggering user's nickname, argument has to be of type string. YAGPDB's highest role has to be above the highest role of the member. |
| Function returns Member object having above methods.
|
| Returns the count of online users/members on current server. |
| Returns the count of online bots. |
Member object in Discord documentation.
Field | Description |
.Channel.Name | The name of the channel. |
.Channel.ID | The ID of the channel. |
.Channel.ParentID | The ID of the channel's parent (category), returns 0 if none. |
.Channel.Topic | The topic of the channel. |
.Channel.NSFW | Outputs whether this channel is NSFW or not. |
Function | Description |
| Function edits channel's name. |
| Function edits channel's topic/description.
|
| Function returns full channel object of given |
Channel object in Discord documentation.
Field | Description |
.Message.ID | ID of the message. |
.Message.ChannelID | Channel ID this message is in. |
.Message.GuildID | Guild ID in which the message is. |
.Message.Content | Text content on this message. |
.Message.Timestamp | Timestamp of the message in type discordgo.Timestamp (use .Message.Timestamp.Parse to get type time.Time and .Parse.String method returns type string). |
.Message.EditedTimestamp | The time at which the last edit of the message occurred, if it has been edited. As with .Message.Timestamp, it is of type discordgo.Timestamp. |
.Message.MentionRoles | The roles mentioned in the message. |
.Message.MentionEveryone | Whether the message mentions everyone. |
.Message.Author | Author of the message (User object). |
.Message.Attachments | Attachments to this message (slice of attachment objects). |
.Message.Embeds | Embeds on this message (slice of embed objects). |
.Message.Mentions | Users this message mentions. |
.Message.Reactions | Reactions on this message (only available from getMessage). |
.Message.Type | The type of the message. |
.Message.Pinned | Whether this message is pinned. |
.Args | List of everything that is passed to .Message.Content. .Args is a slice of type string. |
.Cmd | .Cmd is of type string and shows all arguments that trigger custom command, part of .Args. Starting from |
.CmdArgs | List of all the arguments passed after |
.StrippedMsg | "Strips" or cuts off the triggering part of the message and prints out everything else after that. Bear in mind, when using regex as trigger, for example |
Message object in Discord documentation.
More information about the Message
object can be found here.
This is available and part of the dot when reaction trigger type is used.
Field | Description |
.Reaction | Returns reaction object which has following fields |
.ReactionMessage | Returns the message object reaction was added to.
Returns emoji count and their name. Has an alias .Message and works it works the same way. |
.ReactionAdded | Returns a boolean type bool true/false indicating whether reaction was added or removed. |
Reaction object in Discord documentation.
Time in general uses Golang's time package library > https://golang.org/pkg/time/#time and also this although slightly different syntax all applies here > https://gobyexample.com/time.
Field | Description |
.DiscordEpoch | Gives you Discord Epoch time in time.Time. |
.UnixEpoch | Gives you Unix Epoch time in time.Time. |
.TimeHour | Variable of time.Duration type and returns 1 hour > |
.TimeMinute | Variable of time.Duration type and returns 1 minute > |
.TimeSecond | Variable of time.Duration type and returns 1 second > |
Function | Description |
| Gets the current time, value is of type time.Time which can be used in a custom embed. More info here. |
| Outputs given time in RFC822 formatting, first argument |
| Returns given integer (whole number) or time.Duration argument in nanoseconds in human readable format - as how long it would take to get towards given time - e.g. |
| Sames as |
| Sames as both humanize functions above, this time duration is returned in seconds - e.g. |
| Returns time passed since given argument of type time.Time in human readable format - e.g. |
| Returns new type time.Time object in UTC using given syntax (all arguments need to be of type int), for example >
|
To demonstrate humanizeDurationHours
and also how to parse a timestamp, output will be like whois
command shows user's join server age.
{{humanizeDurationHours (currentTime.Sub .Member.JoinedAt.Parse)}}
To demonstrate newDate
to get Epoch times.
{{$unixEpoch := newDate 1970 1 1 0 0 0}} in seconds > {{$unixEpoch.Unix}}
{{$discordEpoch := newDate 2015 1 1 0 0 0}} in seconds > {{$discordEpoch.Unix}}
Golang has built-in primitive data types (int, string, bool, float64, ...) and built-in composite data types (array, slice, map, ...) which also are used in custom commands. YAGPDB's templating "engine" has currently two user-defined, custom data types - templates.Slice and templates.SDict. There are other custom data types used like discordgo.Timestamp, but these are outside of the main code of YAGPDB, so not explained here further. Type time.Time is covered in it's own section. Custom Types section discusses functions that initialize values carrying those templates.Slice (abridged to cslice), templates.SDict (abridged to sdict) types and their methods. Both types handle type interface{} element. It's called an empty interface which allows a value to be of any type. So any argument of any type given is handled. (In "custom commands"-wise mainly primitive data types, but slices as well.)
templates.Slice
- This is a custom composite data type defined using an underlying data type []interface{} . It is of kind slice (similar to array) having interface{} type as its value and can be initialized using cslice
function. Retrieving specific element inside templates.Slice is by indexing its position number.
Function | Description |
| Function creates a slice of type templates.Slice that can be used elsewhere (as an argument for Example: |
Method | Description |
.Append arg | Creates a new cslice having given argument appended fully by its type to current value. Has max size of 10 000 length. |
.AppendSlice arg | Creates a new cslice from argument of type slice appended/joined with current value. Has max size of 10 000 length. |
.Set int value | Changes/sets given int argument as index position of current cslice to new value. Note that .Set can only set indexes which already exist in the slice. |
.StringSlice strict-flag | Compares slice contents - are they of type string, based on the strict-flag which is boolean and is by default false. Under these circumstances if the element is a string then those elements will be included as a part of the []string slice and rest simply ignored. Also time.Time elements - their default string notation will be included. If none are string an empty []string slice is returned. If strict-flag is set to true it will return a []string only if all elements are pure string, else Example in this section's Snippets. |
To demonstrate .StringSlice {{(cslice currentTime.Month 42 "YAPGDB").StringSlice}}
will return a slice [February YAGPDB]
. If the flag would have been set to true - {{...).StringSlice true}}, all elements in that slice were not strings and <no value>
is returned.
General example:
Creating a new cslice: {{ $x := (cslice "red" "red") }} **{{ $x }}**Appending to current cslice dataand assigning newly created cslice to same variable:{{ $x = $x.Append "green" }} **{{ $x }}**Setting current cslice value in position 1:{{ $x.Set 1 "blue" }} **{{ $x }}**Appending a slice to current cslice databut not assigning newly created cslice to same variable:**{{ $x.AppendSlice (cslice "yellow" "magenta") }}**Variable is still: **{{ $x }}**Type of variable: **{{ printf "%T" $x }}**
templates.SDict
- This is a custom composite data type defined on an underlying data type map[string]interface{}. This is of kind map having string type as its key and interface{} type as that key's value and can be initialized using sdict
function. A map is key-value store. This means you store value and you access that value by a key. Map is an unordered list and the number of parameters to form key-value pairs must be even. Retrieving specific element inside templates.Sdict is by indexing its key.
Function | Description |
| Like dict function, creating a templates.SDict type map, key must be of type string. Can be used for example in Example: |
Method | Description |
.Del "key" | Deletes given key from sdict. |
.Get "key" | Retrieves given key from sdict. |
.Set "key" value | Changes/sets given key to a new value or creates new one, if no such key exists in sdict. |
Creating sdict: {{ $x := sdict "color1" "green" "color2" "red" }} **{{ $x }}**Retrieving key "color2": **{{ $x.Get "color2" }}**Changing "color2" to "yellow": {{ $x.Set "color2" "yellow" }} **{{ $x }}**Adding "color3" as "blue": {{ $x.Set "color3" "blue" }} **{{ $x }}**Deleting key "color1" {{ $x.Del "color1" }} and whole sdict: **{{ $x }}**
Since both templates.SDict (sdict) and templates.Slice (cslice) are custom composite data types, this type information is lost while saving to a database or passing as data to scheduled execCC
or scheduleUniqueCC
(which internally involves saving to database). Thus, they are converted to their underlying data types map[string]interface{} and []interface{} respectively.
They can be converted back to templates.SDict and templates.Slice as follows :
For sdict -
{{$sdict := sdict "a" 1 "b" "two"}}
{{dbSet 0 "example" $sdict}}
{{$map := (dbGet 0 "example").Value}}
{{$sdict_converted := sdict $map}}
For cslice -
{{$cslice := cslice 1 "two" 3.0}}
{{dbSet 0 "example" $cslice}}
{{$slice := (dbGet 0 "example").Value}}
{{$cslice_converted := (cslice).AppendSlice $slice}}
The above examples use some database specific functions which are explained here.
Functions are underappreciated. In general, not just in templates. // Rob Pike
Function | Description |
| Traverses given |
| Function converts exported field-value pairs of a struct to an sdict. For example it is useful for editing embeds, rather than having to reconstruct the embed field by field manually. Exampe: |
| Function converts input to a slice of bytes - meaning []uint8. |
| Converts the argument, number or string to type time.Duration. Number represents nanoseconds. String can be with time modifier (second, minute, hour, day etc) |
| Converts argument (int or string type of a number) to type float64. Usage: |
| Converts something into an integer of type int. Usage: |
| Converts something into an int64. Usage: |
| Function converts input to a slice of runes - meaning []int32. |
| Has alias |
To demonstrate toDuration
, outputs 12 hours from current time in UTC.
{{(currentTime.Add (toDuration (mult 12 .TimeHour))).Format "15:04"}}
is the same as{{(currentTime.Add (toDuration "12h")).Format "15:04"}}
or{{(currentTime.Add (toDuration 43200000000000)).Format "15:04"}}
Tip: You can convert a Unicode code point back to its string equivalent using printf "%c"
. For example, printf "%c" 99
would result in the string c
as 99
is the Unicode code point for c
.printf
is briefly covered later on in the next section, further documentation can be found here.
Function | Description |
| Joins several strings into one, separated by the first argument |
| Converts the string to lowercase. |
| Converts the string to uppercase. |
| Function's first argument must be of type string or slice. Outputs the "string" after cutting/slicing off integer (numeric) value of symbols (actually starting the string's index from integer through integer2) - e.g. This |
| Escapes the string so it can be safely placed inside a URL path segment - e.g. "Hello, YAGPDB!" becomes "Hello%2C%20YAGPDB%21" |
| Splits given |
| Returns string with the first letter of each word capitalized. |
| Compares "string" to regex pattern and returns first match. |
| Adds all regex matches from the "string" to a slice. Example in section's Snippets. |
| Returns whole-pattern matches and also the sub-matches within those matches as slices inside a slice. |
| Replaces "string1" contents with "string2" at regex match point. |
| These are GO template package's predefined functions and are aliases for fmt.Sprint, fmt.Sprintf and fmt.Sprintln. Formatting is also discussed here.
|
Special information we can include in the string is escape sequences. Escape sequences are two (or more) characters, the first of which is a backslash \
, which gives the remaining characters special meaning - let's call them metacharacters. The most common escape sequence you will encounter is \n
, which means "newline".
With regular expression patterns - when using quotes you have to "double-escape" metacharacters starting with backslash. You can use backquotes/ticks to simplify this:{{reFind "\\d+" (toString 42)}}
versus {{reFind `\d+` (toString 42)}}
{{$args:= (joinStr " " (slice .CmdArgs 1))}}
Saves all the arguments except the first one to a variable $args
.
To demonstrate usage of split
function. >
{{$x := "Hello, World, YAGPDB, here!"}} {{range $k, $v := (split $x ", ")}}Word {{$k}}: __{{$v}}__ {{end}}
To demonstrate usage of reFindAll
. >
Before regex: {{$msg := "1 YAGPDB and over 100000 servers conquered."}} {{$re2 := reFindAll "[0-9]+" $msg}} {{$msg}}
After regex matches: {{joinStr " " "Only" (index $re2 0) "YAGPDB and already" (index $re2 1) "servers captured."}}
Function | Description |
| Returns x + y + z + ..., detects first number's type - is it int or float and based on that adds. (use |
| Returns x - y -z - ... Works like add, just subtracts. |
| Multiplication, like |
| Division, like |
| Meant specifically for floating point numbers division. |
| Log is a logarithm function using (log base of x). Arguments can be any type of numbers, as long as they follow logarithm logic. Return value is of type float64. If base argument is not given It is using natural logarithm (base e - The Euler's constant) as default, also is the default to change the base. |
| Mod returns the floating-point remainder of x/y. |
| Pow returns x**y, the base-x exponential of y which have to be both numbers. Type is returned as float64. |
| Returns a random integer between 0 and stop, or start - stop if two args are provided. Result will be |
| Returns the nearest integer, rounding half away from zero. Regular rounding > 10.4 is |
| Returns the least integer value greater than or equal to input or rounds up. |
| Returns the greatest integer value less than or equal to input or rounds down. |
| Returns the nearest integer, rounding ties to even.
|
| Returns the square root of a number as type float64.
|
{{$d := randInt 10}}
Stores random int into variable $d
(a random number from 0-9).
To demonstrate rounding float to 2 decimal places.
{{div (round (mult 12.3456 100)) 100}}
returns 12.35
{{div (roundFloor (mult 12.3456 100)) 100}}
returns 12.34
Function | Description |
| Same as |
| Adds each emoji as a reaction to the message that triggered the command (recognizes Unicode emojis and |
| Adds each emoji as a reaction to the response message (recognizes Unicode emojis and |
|
|
| Special case for |
| Deletes all reactions pointed message has. |
| Deletes reaction(s) from a message. |
| Deletes message with given |
| Deletes the response after a certain time from optional |
| Deletes the trigger after a certain time from optional |
| Edits the message in channel, channel can be either |
| Edits the message in channel and has same logic in escaping characters as |
| Returns a Message object. |
| Sends the user a direct message, only one DM can be sent per custom command (accepts embed objects). YAG will only DM triggering user. |
| Sends |
| Sends |
| Same as |
| Same as |
Sends message to current channel nil
and gets messageID to variable $x
. Also adds reactions to this message. After 5 seconds, deletes that message. >
{{$x := sendMessageRetID nil "Hello there!"}} {{addMessageReactions nil $x "👍" "👎"}} {{deleteMessage nil $x 5}}
To demonstrate sleep
and slightly also editMessage
functions. >
{{$x := sendMessageRetID nil "Hello"}} {{sleep 3}} {{editMessage nil $x "There"}} {{sleep 3}} {{sendMessage nil "We all know, that"}} {{sleep 3}} YAGPDB rules!
To demonstrate usage of complexMessage
with sendMessage
. {{sendMessage nil (complexMessage "content" "Who rules?" "embed" (cembed "description" "YAGPDB of course!" "color" 0x89aa00) "file" "Here we print something nice - you all are doing awesome!")}}
To demonstrate usage of complexMessageEdit
with editMessage
.
{{$mID := sendMessageRetID nil (complexMessage "content" "You know what is..." "embed" (cembed "title" "FUN!?" "color" 0xaa8900))}} {{sleep 3}} {{editMessage nil $mID (complexMessageEdit "embed" (cembed "title" "YAGPDB!" "color" 0x89aa00) "content" "Yes, it's always working with...")}}{{sleep 3}}{{editMessage nil $mID (complexMessageEdit "embed" nil "content" "Embed deleted, goodbye YAG!")}}{{deleteMessage nil $mID 3}}
Function | Description |
| Mentions |
| Mentions |
| Mentions the first role found with the provided name (case-insensitive). |
| Mentions the role found with the provided ID. |
<@{{.User.ID}}>
Outputs a mention to the user that called the command and is the same as {{.User.Mention}}
<@###########>
Mentions the user that has the ID ###### (See How to get IDs to get ID).
<#&&&&&&&&&&&>
Mentions the channel that has ID &&&&&& (See How to get IDs to get ID).
<@&##########>
Mentions the role with ID ######## (listroles command gives roleIDs). This is usable for example with {{sendMessageNoEscape nil "Welcome to role <@&11111111...>"}}
. Mentioning that role has to be enabled server- side in Discord.
Function | Description |
| Adds the role with the given ID to the user that triggered the command (use the |
| Adds the role with given name to the user that triggered the command (use the |
| Gives a role by ID to the target. |
| Gives a role by name to the target. |
| Returns true if the user has the role with the specified ID (use the listroles command for a list of roles). |
| Returns true if the user has the role with the specified name (case-insensitive). |
| Removes the role with the given ID from the user that triggered the command (use the listroles command for a list of roles). |
| Removes the role with given name from the user that triggered the command (use the listroles command for a list of roles). |
| Takes away a role by ID from the target. |
| Takes away a role by name from the target. |
| Returns true if the given user has the role with the specified ID (use the listroles command for a list of roles). Example in section's Snippets. |
| Returns true if the given user has the role with the specified name (case-insensitive). |
To demonstrate usage of targetHasRoleID
. >
{{$x := (userArg (index .Args 1)).ID}} {{if targetHasRoleID $x ############}} Has the Role! {{else}} Does not have the role! {{end}}
Function | Description |
| Returns value of type time.Time and shows when the current user was created. |
| The account age of the current user in more human readable format
(Eg: |
| The account age of the current user in minutes. |
Function | Description |
| Returns a random adjective. |
| Function to generate embed inside custom command. More in-depth here. |
| These functions are covered in their own section here. |
| Creates an unordered collection of key-value pairs, a dictionary so to say. The number of parameters to form key-value pairs must be even. Example here. Keys and values can be of any type. Key is not restricted to string only as in case with |
| Executes a YAGPDB command (e.g. roll, kick etc) in a custom command. Exec can be run max 5 times per command. If real command returns an embed - exec syntax is |
| Functions same way as |
| This function places comma to separate groups of thousands of a number. |
| Returns bool true/false whether case-sensitive value is in list/slice. |
| Returns the result of indexing its first argument by the following arguments. Each indexed item must be a map, slice or array. Example: |
| Same as |
| This function helps to determine what kind of data type we are dealing with. |
| Returns a random noun. |
| Checks the arguments for a specific type. Has methods |
| Required by |
| Iterates (loops) over the given slice or array and sets successive elements as active data (the dot) to be further handled inside the |
| Function sends a formulated template to another channel. Channel is like always either name, number or nil. Also returns messageID. Example: Now we call that "logs" in the same custom command. |
| Works the same way as function above. Only channel's name is not in the arguments. YAGPDB will only DM the triggering user. |
| Creates a new slice of type int, beginning from start number, increasing in sequence and ending at stop (not included). |
| Returns a shuffled, randomized version of a list/slice. |
| Pauses execution of template's action-structure inside custom command for max 60 seconds combined. Argument |
execCC
calls are limited to 1 / CC for non-premium users and 10 / CC for premium users.
Function | Description |
| Function that executes another custom command specified by |
| Same as An example would be a mute command that schedules the unmute action sometime in the future. However, let's say you use the unmute command again on the same user, you would want to override the last scheduled unmute to the new one. This can be used for that. |
| Cancels a previously scheduled custom command execution using |
To demonstrates execCC and .ExecData using the same CC.
{{ $yag := "YAGPDB rules! " }}{{ $ctr := 0 }} {{ $yourCCID := .CCID }}{{ if .ExecData }}{{ $ctr = add .ExecData.number 1 }}{{ $yag = joinStr "" $yag $ctr }} {{ .ExecData.YAGPDB }}{{ else }}So, someone rules.{{ $ctr = add $ctr 1 }} {{ $yag = joinStr "" $yag 1 }}{{ end }}{{ if lt $ctr 5 }}{{ execCC $yourCCID nil 10 (sdict "YAGPDB" $yag "number" $ctr) }}{{ else }} FUN'S OVER! {{ end }}
You have access to a basic set of Database functions, this is almost a key value store ordered by the key and value combined.
You can have max 50 * user_count (or 500 * user_count for premium) values in the database, if you go above this all new write functions will fail, this value is also cached so it won't be detected immediately when you go above nor immediately when you're under again.
Patterns are basic PostgreSQL patterns, not Regexp: An underscore (_)
matches any single character; a percent sign (%)
matches any sequence of zero or more characters.
Keys can be max 256 bytes long and has to be strings or numbers. Values can be anything, but if they go above 100KB they will be truncated.
You can just pass a userID
of 0 to make it global (or any other number, but 0 is safe).
There can be 10 database interactions per CC, out of which dbTop/BottomEntries, dbCount and dbGetPattern may be only run twice. (50,10 for premium users).
Example here.
Function | Description |
| Sets the value for the specified |
| Same as |
| Increments the value for specified key for the specified user, if there was no value then it will be set to |
| Retrieves a value from the database for the specified user, this returns DBEntry object. |
| Retrieves up to |
| Retrieves |
| Deletes the specified key for the specified value from the database. |
| Deletes database entry by it's ID. |
| Returns |
| Returns |
| Returns the count of all database entries which are not expired. Optional arguments: if |
Fields | Description |
.ID | ID of the entry. |
.GuildID | ID of the server. |
.UserID | ID of the user. |
.User | |
.CreatedAt | When this entry was created. |
.UpdatedAt | When this entry was last updated. |
.ExpiresAt | When entry will expire. |
.Key | The key of the entry. |
.Value | The value of the entry. |
Branching using if
action's pipeline and comparison operators - these operators don't need to be inside if
branch. if
statements always need to have an enclosing end
.
eq
, though often used with 2 arguments (eq x y
) can actually be used with more than 2. If there are more than 2 arguments, it checks whether the first argument is equal to any one of the following arguments. This behaviour is unique to eq
.
Comparison operators always require the same type: i.e comparing 1.23
and 1
would throw incompatible types for comparison
error as they are not the same type (one is float, the other int). To fix this, you should convert both to the same type -> for example, toFloat 1
.
Case | Example |
if |
Initialization statement can also be inside |
else if |
You can have as many |
else |
|
not |
|
and |
|
or |
|
Equal: eq |
|
Not equal: ne |
|
Less than: lt |
|
Less than or equal: le |
|
Greater than: gt |
|
Greater than or equal: ge |
|
range
iterates over element values in variety of data structures in pipeline - slices/arrays, maps or channels. The dot .
is set to successive elements of those data structures and output will follow execution. If the value of pipeline has zero length, nothing is output or if an {{else}}
action is used, that section will be executed.
Affected dot inside range
is important because methods mentioned above in this documentation:.Server.ID
, .Message.Content
etc are all already using the dot on the pipeline and if they are not carried over to the range
control structure directly, these fields do not exists and template will error out. Getting those values inside range
and also with
action would need $.User.ID
for example.
range
on slices/arrays provides both the index and element for each entry; range on map iterates over key/element pairs. If a range action initializes a variable, that variable is set to the successive elements of the iteration. Range can also declare two variables, separated by a comma and set by index and element or key and element pair. In case of only one variable, it is assigned the element.
Like if
, range
is concluded with{{end}}
action and declared variable scope inside range
extends to that point.
{{/* range over a slice */}}{{ range $index, $element := cslice "YAGPDB" "IS COOL!" }}{{ $index }} : {{ $element }} {{ end }}{{/* range on a map */}}{{ range $key, $value := dict "SO" "SAY" "WE" "ALL!" }}{{ $key }} : {{ $value }} {{ end }}{{/* range with else and variable scope */}}{{ range seq 1 1 }} no output {{ else }} output here {{ end }}{{ $x := 42 }} {{ range $x := seq 2 4 }} {{ $x }} {{ end }} {{ $x }}
Custom command response was longer than 2k (contact an admin on the server...) This is quite common error users will get whilst using range. Simple example to reproduce it: {{ range seq 0 400 }} {{ $x := . }} {{ end }} HELLO! This will happen because of whitespaces and newlines, so make sure you one-line the range or trim spaces, in this context {{- $x := . -}}
with
lets you assign and carry pipeline value with its type as a dot .
inside that control structure, it's like a shorthand. If the value of the pipeline is empty, dot is unaffected and when {{else}}
is used, that branch is executed instead.
Affected dot inside with
is important because methods mentioned above in this documentation:.Server.ID
, .Message.Content
etc are all already using the dot on the pipeline and if they are not carried over to the with
control structure directly, these fields do not exists and template will error out. Getting those values inside with
and also range
action would need $.User.ID
for example.
Like if
and range
actions, with
is concluded using {{end}}
and variable scope extends to that point.
{{/* Shows the scope and how dot is affected by object's value in pipeline */}}{{ $x := "42" }} {{ with and ($z:= seq 0 5) ($x := seq 0 10) }}len $x: `{{ len $x }}`{{/* "and" function uses $x as last value for dot */}}same as len dot: `{{ len . }}`but len $z is `{{ len $z }}` {{ end }}Outer-scope $x len however: {{ len $x }}{{/* when there's no value, dot is unaffected */}}{{ with false }} dot is unaffected {{ else }} printing here {{ .CCID }} {{ end }}
{{if hasRoleName "funrole"}} Has role funrole {{end}}
This will only respond if the member has a role with name "funrole" .
{{if gt (len .Args) 0}} {{index .Args 1}} {{end}}
Assuming your trigger is a command, will display your first input if input was given.
{{if eq .Channel.ID #######}} YAG! {{end}}
Will only show YAG!
if ChannelID is #####.
{{if ne .User.ID #######}} YAG! {{end}}
Will ignore if user ID equal to ##### uses command.
{{addReactions .CmdArgs}}
Adds the emoji following a trigger as reactions.
{{$a := (exec "catfact")}}
Saves the response of the catfact
command to variable $a
.
{{$allArgs := (joinStr " " .CmdArgs)}}
Saves all the arguments after trigger to a variable $allArgs
.
{{/* this is a comment */}}
For commenting something inside a template, use this syntax. May contain newlines. Comments do not nest and they start and end at the delimiters.
To trim spaces, for example >{{- /* this is a multi-line
comment with whitespace trimmed from preceding and following text */ -}}
Using{{- ... -}}
is also handy insiderange
actions, because whitespaces and newlines are rendered there as output.
To demonstrate sleep and slightly also editMessage functions. >
{{$x := sendMessageRetID nil "Hello"}} {{sleep 3}} {{editMessage nil $x "There"}} {{sleep 5}} {{sendMessage nil "We all know, that"}} {{sleep 3}} YAGPDB rules!