2 Events and cronjobs
Yessiest edited this page 2022-05-21 17:05:15 +00:00

Cron - asynchronous automation

The name of this module might sound familiar to some of you coming from the Linux(Unix) background. That is, indeed, because this module draws its inspiration from a daemon named cron. Sharing some similarities with it, this module adds some more functionality to the regular cron syntax.

In general, the cron module provides a way to execute commands in a particular time or according to a particular event.

All of the event types below can be created using the &event command (assuming that & is the prefix)

Cronjobs

A cronjob is a syntactic construction that tells cron that a certain command should be executed at a given time. There are 2 valid syntax forms for a cronjob:

  1. The generic cronjob syntax
+---------- minute (0-59)
| +-------- hour (0-23)
| | +------ day of month (1-31)
| | | +---- month (1-12)
| | | | +-- day of week (1-7)
| | | | |
v v v v v
n n n n n command

Every n is either a number, an asterisk (*), a modulo predicate(*/n) or a list (n,n,n,...) (see Appendix 1)

  1. The single use syntax
DD.MM.YY HH:MM command

(Note: HH:MM DD.MM.YY is also valid, as well as DD.MM.YYYY HH:MM)

DD.MM.YY is a date format, with day, month and year separated by a dot. HH:MM is a 24-hour time format.

Event directives

As with the modern cron implementations on Linux(Unix), there are multiple "directives" for cron. Unlike these implementations, directive syntax is a bit more complex, allowing matching against certain arguments passed along with the directive.

Directive example

Rather than explaining the directives from scratch, let's look at a practical example:

@message /%sGNU\/Linux%s/ >913818433748086784 : &echo *funni stallman bad copypasta goes here by $USERNAME*
@message /%sGNU\/Linux%s/ <913818433748086784 : &echo *funni stallman bad copypasta goes here by $USERNAME*

This might look very confusing to those of you who are used to the @reboot directive in cron. But in fact, it's not unlike that directive - it's just that after the @message directive we have 2 arguments that are being matched. In this case, it's the message itself and the message author's id. To separate the arguments list from the command, we use a colon : delimiter. Now, let's look at what each argument does:

  1. /%sGNU\/Linux%s/ is a Lua regex pattern that matches every message containing a space-separated string "GNU/Linux".
  2. >913818433748086784 (<913818433748086784) is a numeric comparison pattern that takes a string, converts it to a number (if possible), and then compares it to the pattern (so for example if our bot's id is "913818433748086784", these 2 directives will match any user id that is greater or lesser than the numeric value of the bot's id (practically, it means that it will match any id that isn't the bot's id))

We finalize the argument list with :. Note that it should be separated from both sides with spaces.

There is also a channel id argument for message, but since the directives don't specify any patter to match it against, this argument is simply ignored. For any given directive, any amount of arguments can be ignored.

Last but not least, directives can pass certain arguments to the command itself as environment variables. In our example, $USERNAME is an environment variable. Those of you who are knowledgeable about the ways of Unix shells already know what this means. Those of you who don't might want to read the next paragraph.

Environment variables

Most of the events that are currently available pass some environment variables to the command, which can be used to manipulate the command. For example, if a @message event is triggered, the $USERNAME environment variable is changed to the username of the message author. All environment variables are prefixed with a dollar sign $ and can only be used inside of the command.

Argument matching patterns

There are multiple patterns available, each one can be applied to any argument:

  1. /.../ is a regex pattern that matches the argument against a Lua-style regular expression (See Programming in Lua)
  2. >n, <n, >=n, <=n is a numeric comparison pattern that converts argument to a numeric value (if possible) and then compares it against number n
  3. n is a separate numeric comparison pattern that converts argument to a numeric value and checks if both the argument and the number n are equal.
  4. "..." and '...' are both string comparison patterns that check that the argument matches against the string enclosed in the quotes.
  5. * is a pattern that matches any argument. It's a short form of the regex pattern /.*/.

Note that while both "..." and n are equivalent when used against numbers, n will fail to compare non-numeric arguments because it converts the argument to a number.

Available directives

Currently, the directives list is very short, but as updates will come along, this list will expand.

Format is @<directive name> <argument> <argument2> ... <$VARIABLE> <$VARIABLE2> <VARIABLE3>

  1. @message: content, userId, channelId, $USER, $USERNAME, $CHANNEL, $CONTENT
  2. @messageOnce: content, userId, channelId, $USER, $USERNAME, $CHANNEL, $CONTENT
  3. @ban: userId, $USER, $USERNAME
  4. @banOnce: userId, $USER, $USERNAME
  5. @unban: userId, $USER, $USERNAME
  6. @unbanOnce: userId, $USER, $USERNAME
  7. @join: userId, username, age, $USER, $USERNAME, $AGE, $DISCRIM, $TAG
  8. @joinOnce: userId, username, age, $USER, $USERNAME, $AGE, $DISCRIM, $TAG
  9. @leave: userId, username, role, $USER, $USERNAME, $AGE, $DISCRIM, $TAG, $GUILDTIME, $ROLE
  10. @leave: userId, username, role, $USER, $USERNAME, $AGE, $DISCRIM, $TAG, $GUILDTIME, $ROLE

Argument description:

  • content - Message content.
  • userId - Discord ID of the user that triggered the event.
  • username - Discord username of the user that triggered the event.
  • age - Discord account age in seconds.
  • role - Primary role ID of the discord user that triggered the event.
  • channelId - ID of the channel where the event was triggered.

Environment variable description:

  • $USER - User ID that triggered the event.
  • $USERNAME - Username that triggered the event.
  • $AGE - Discord account age in seconds.
  • $DISCRIM - Discriminator (last 4 digits) of a full Discord tag.
  • $TAG - Full discord tag.
  • $GUILDTIME - Time spent in the guild in seconds.
  • $ROLE - Primary role of the user.
  • $CHANNEL - Channel where the event occured.

Examples

  1. Printing a bump reminder every 2 hours
* */2 * * * &echo bump
  1. Printing a one-time reminder to yourself
15:40 10.09.22 &pingself important stuff
  1. Watching people say bad words
@message /^[oO][vV][hH]$/ : &message Somebody said a bad word!

Delay command

There is one special type of command that utilizes the cron system - the &delay command. It recognizes time delay in format <number><time unit>, where time unit is one of the following:

  1. h - hour
  2. m - minute
  3. d - day
  4. w - week
  5. y - year

As an example, to execute a command after 2 days, 1 week and 6 hours, one could write the following:

&delay 2d1w6h &command

or

&delay 1w6h2d &command

Appendix 1.

In the Linux(Unix) cron syntax there exist multiple syntactic facilities for matching a range of time.

  1. * matches every number possible (so, if it's in place of month, the command would execute every month)
  2. */n matches ever n-th number (if it's in place of minute with n=30, then the command will execute every time the minute value is evenly divisble by 30 (NOTE: While in this case the command will indeed execute every 30 minutes, this does not mean that for n=45 it will execute every 45 minutes. Instead, it will only execute when minute value is exactly 45.))
  3. n,n,n matches any of the numbers that are in the comma-separated list of numbers (if we have a list 14,16,18 in place of hour, the command will execute at 2 PM, 4 PM and 6 PM, respectively.)