Skip to content

Actions / Conditions

Conditions

Message conditions

  • message-matches-any
    Is true if any of the patterns that you list are found in the message's content. This kind of searching might be inconvenient in certain use cases: if you prefer to look for whole words instead see the condition message-contains-word
    Accepts: A list of patterns. Patterns can make use of wildcards such as * and ?
    Context: message
    Example:
    - message-matches-any: ["cat"] # This will only match exactly this word
    # I like cats -> Is false
    # cat -> Is true
    # cats -> Is false
    - message-matches-any: ["*cat*"] # The wildcard "*" represents any multiple characters
    # I like cats -> Is true
    # I like cat -> Is true
    # I like c4t -> Is false
    - message-matches-any: ["*c?t*"] # The wildcard "?" represents any single character
    # I like cats -> Is true
    # I like cat -> Is true
    # I like c4t -> Is true
    # xxxxcatxxxx -> Is true
    
  • message-matches-regex
    Is true if the regex returns a match against the message's content
    Accepts: A string representing a regular expression. Remember that \ must be escaped: turn all \ characters to \\ when entering the rule.
    Context: message
  • message-has-attachment
    Will check if the message contains an attachment
    Accepts: A bool (true or false)
    Context: message
  • message-contains-word
    Is true if any of the words you list are found in the message. It does what it is most commonly know "whole word search". Patterns are supported
    Example:
    - message-contains-word: ["cat"]
    # I like cats -> Is false
    # I like cat -> Is true
    # I like c4t -> Is false
    # xxxxcatxxxx -> Is false
    - message-contains-word: ["c?t"] # The wildcard "?" represents any single character
    # I like cats -> Is false
    # I like cat -> Is true
    # I like c4t -> Is true
    # xxxxcatxxxx -> Is false
    
  • message-contains-url
    Will check if the message contains a clickable URL.
    Note: URLs lacking a protocol (http/https) will not be detected.
    Accepts: A bool (true or false)
    Context: message
  • message-contains-invite
    Will check if the message contains a standard Discord invite. Invites that belong to the server are ignored.
    Accepts: A bool (true or false)
    Context: message
  • message-contains-media
    Will check if the message contains any media link (picture or video)
    Accepts: A bool (true or false)
    Context: message
  • message-contains-more-than-mentions
    Will check if the message contains more than X user mentions.
    Accepts: A number representing the number of mentions
    Context: message
  • message-contains-more-than-unique-mentions
    Will check if the message contains more than X unique user mentions. As opposed to the non-unique variant the mentioned users are being counted, not just the mentions themselves.
    Accepts: A number representing the number of unique mentions.
    Context: message
  • message-contains-more-than-role-pings
    Will check if the message contains more than X unique role mentions. Only mentions that result in a ping will be counted.
    Accepts: A number representing the number of role mentions
    Context: message
  • message-contains-more-than-emojis
    Will check if the message contains more than X emojis. Important: emojis with modifiers, such as a thumbs up emoji with custom skin color, will be considered 2 separate emojis.
    Accepts: A number representing the number of emojis.
    Context: message
  • message-has-more-than-characters
    Will check if the message contains more than X characters. Emojis and custom emojis will be considered a single character. Mentions, both users and channels, are counted too.
    Accepts: A number representing the number of characters.
    Context: message

User conditions

  • user-id-matches-any
    Is true if any of the IDs that you list match the user's ID
    Accepts: A list of IDs (numbers)
    Context: user
    Example: user-id-matches-any: [123456789, 2626262626]
  • username-matches-any
    Is true if any of the patterns that you list are found in the user's username
    Accepts: A list of patterns. Patterns can make use of wildcards such as * and ?
    Context: user
  • username-matches-regex
    Is true if the regex returns a match against the user's username
    Accepts: A string representing a regular expression. Remember that \ must be escaped: turn all \ characters to \\ when entering the rule.
    Context: user
  • nickname-matches-any
    Is true if any of the patterns that you list are found in the user's nickname
    Accepts: A list of patterns. Patterns can make use of wildcards such as * and ?
    Context: user
  • nickname-matches-regex
    Is true if the regex returns a match against the user's nickname
    Accepts: A string representing a regular expression. Remember that \ must be escaped: turn all \ characters to \\ when entering the rule.
    Context: user
  • display-name-matches-any
    Is true if any of the patterns that you list are found in the user's display name.
    The display name can be the user's server specific nickname, if they have one set, otherwise it's their global name or their username.
    Accepts: A list of patterns. Patterns can make use of wildcards such as * and ?
    Context: user
  • display-name-matches-regex
    Is true if the regex returns a match against the user's display name.
    The display name can be the user's server specific nickname, if they have one set, otherwise it's their global name or their username.
    Accepts: A string representing a regular expression. Remember that \ must be escaped: turn all \ characters to \\ when entering the rule.
    Context: user
  • user-activity-matches-any
    Is true if any of the patterns that you list are found in any of the user's activities
    Accepts: A list of patterns. Patterns can make use of wildcards such as * and ?
    Context: user
  • user-status-matches-any
    Is true if any of the statuses that you list are the user's current status
    Accepts: A list of statuses. Can be online, idle, dnd or offline
    Context: user
  • user-created-less-than
    Is true if the user's account has been created less than ago.
    Accepts: A timedelta. Or a number, representing the amount of hours to be checked
    Context: user
    Example: user-created-less-than: 2 hours
  • user-joined-less-than
    Is true if the user has joined the server less than ago.
    Accepts: A timedelta. Or a number, representing the amount of hours to be checked
    Context: user
    Example: user-joined-less-than: 2 hours
  • user-has-default-avatar
    Will check if the user has a default Discord avatar
    Accepts: A bool (true or false)
    Context: user
    Example: user-has-default-avatar: true will be true if the profile picture is a default one
  • user-has-sent-less-than-messages
    Will check if the user has sent less than X messages in the server. Important: Defender, by default, counts how many messages a user sends in a server. This does not check the real total number of messages a user has sent in a server since its creation.
    Accepts: A number representing the number of messages
    Context: user
  • user-is-rank
    Will check if the user is the specified rank. This condition allows for rank-specific Warden rules and grants more granular control compared to the standard rank parameter, which merely indicates the maximum rank a rule will have effect on.
    Accepts: A number representing the rank the user must belong to
    Context: user

Channel conditions

  • channel-matches-any
    Will check if the message was sent in any of the specified channels / threads
    Accepts: A list of channel names or IDs / thread IDs
    Context: message
    Example: channel-matches-any: [general, testing, 483223782] will be true if the message was sent in any of these channels
  • category-matches-any
    Will check if the channel in which the message was sent belongs to any of the specified categories.
    Accepts: A list of category names or IDs
    Context: message
  • channel-is-public
    Will check if the message was sent in a publicly viewable channel.
    Accepts: A bool (true or false)
    Context: message

Server conditions

  • in-emergency-mode
    Will check if the server is in emergency mode, either manual or automatic
    Accepts: A bool (true or false)
    Context: Any

Roles conditions

  • user-has-any-role-in
    Is true if the user belongs to any of these roles in the list
    Accepts: A list of role names or IDs
    Context: user
    Example: user-has-any-role-in: [12345678, spider-fighter] will be true if the user belongs to any of these roles
  • is-staff
    Will check if the user is a staff member
    Accepts: A bool (true or false)
    Context: user
  • is-helper
    Will check if the user is a Defender helper
    Accepts: A bool (true or false)
    Context: user

Heat level conditions

  • user-heat-is
    Is true if the user has the specified heat level
    Accepts: A number between 0 and 100
    Context: user
  • user-heat-more-than
    Is true if the user exceeds the specified heat level
    Accepts: A number between 0 and 100
    Context: user
  • channel-heat-is
    Is true if the channel has the specified heat level
    Accepts: A number between 0 and 100
    Context: message
  • channel-heat-more-than
    Is true if the channel exceeds the specified heat level
    Accepts: A number between 0 and 100
    Context: message
  • custom-heat-is
    Is true if the custom heat has the specified level
    Accepts: A list with two elements: the custom heat level name and a number between 0 and 100. Rule name and IDs context variables are available for the name.
    Context: Any
  • custom-heat-more-than
    Is true if the custom heat exceeds the specified level
    Accepts: A list with two elements: the custom heat level name and a number between 0 and 100. Rule name and IDs context variables are available for the name.
    Context: Any

Custom conditions

  • compare
    Compares two values. Supports a variety of operators, textual and numeric. The comparison is case sensitive. This is most useful when used in conjunction with context variables. Using numeric operators with non-numeric values will raise an error.
    Supported operators: ==, !=, contains, contains-pattern, >=, <=, <, >
    contains-pattern supports a pattern, just like the condition message-matches-any and it's case insensitive.
    Example:
    - compare: [abc, "==", abc] # True
    - compare: [2, "<", 1] # False
    
    - var-assign: [value1, "I like bots"]
    - var-assign: [value2, "bots"]
    - compare: [$value2, "contains", $value1] # True. Notice the $ symbol which denotes the use of context variables.
    
    Context: Any

Actions

  • send-message
    Will send a message to the defined destination. Message editing is also supported. The message may include an embed. Please refer to the examples to understand its use.
    Accepts: A map with the destination, the message's content and the embed. Or a list with 2 elements, destination and message content
    Context: Any

User actions

  • set-user-nickname
    Will change the nickname of a user
    Accepts: A string representing the new nickname to set. Supports context variables.
    Context: user
  • delete-user-message
    Will delete the user's message
    Accepts: Nothing
    Context: message
  • add-roles-to-user
    Will assign the listed roles to the user
    Accepts: A list of roles (names / IDs)
    Context: user
  • remove-roles-from-user
    Will remove the listed roles from the user
    Accepts: A list of roles (names / IDs)
    Context: user
  • ban-user-and-delete
    Will ban the user from the server and delete X days worth of messages
    Accepts: A number representing the days worth of messages to delete
    Context: user
  • kick-user
    Will kick the user from the server
    Accepts: Nothing
    Context: user
  • softban-user
    Will kick the user from the server and delete 1 days worth of messages
    Accepts: Nothing
    Context: user
  • punish-user
    Will assign to the user the "punish role" that has been set in Defender
    Accepts: Nothing
    Context: user
  • punish-user-with-message
    Will assign to the user the "punish role" and deliver the "punish message" that have been set in Defender (see [p]dset general)
    Accepts: Nothing
    Context: message
  • timeout-user
    Will timeout the user for a set amount of time. The timeout can also be removed.
    Accepts: A string representing the timeout time. Some examples: '5 minutes', '2 hours', '4 days'. Passing nothing will remove the timeout.
    Context: user
  • get-user-info
    Gets an attribute from an arbitrary user and assigns it to a variable. Many of the standard discord.py Member attributes are supported.
    Additionally, the attributes
    is_staff - is_helper with return value true or false
    rank which returns the rank's number
    message_count which returns the number of messages recorded by Defender
    are available.
    If the user cannot be found an error will be raised.
    Accepts: The ID of a user (context variables are supported) and a map with the attribute to fetch as the value and the target variable as the key.
    Context: Any
    Example:
    - get-user-info: [$user_id, {joined: joined_at, created: created_at}]
    - send-message: [$channel_id, "Your join date is $joined. Your account creation date is $created."]
    
    # Long form
    - get-user-info:
        id: 123456789
        mapping:
           joined: joined_at
           created: created_at
           staff: is_staff
           helper: is_helper
    

Staff notifications

  • notify-staff
    Will send a message to staff's notification channel. The message may include an embed. Please refer to the examples to understand its use.
    Accepts: A string representing the message to send. Or a map that describes the embed and all the behaviors of the notification.
    Context: Any
  • send-mod-log
    Will create a new mod-log case of the last expel action issued by the rule
    Accepts: A string representing the reason of the expel action. Supports context variables.
    Context: Any
  • send-to-monitor
    Will send a message to Defender's monitor, [p]defender monitor
    Accepts: A string representing the message to send. Supports context variables.
    Context: Any
  • warnsystem-warn
    Will warn one or more users using the WarnSystem cog.
    This is an integration: the 3rd party cog WarnSystem must be installed and loaded.
    Accepts: See example
    Context: Any
    Example:
    # Mutes a user for 4 hours
    - warnsystem-warn: [2626262626, 2, "Spammer", "4 hours"]
    
    # Long form is also supported and it handles most attributes found in the API.
    # Documentation TBA. PRs welcome :-)
    

Server actions

  • set-channel-slowmode
    Will set (or deactivate) slowmode of the channel in the context's message
    Accepts: A string representing the slowmode time. Some examples: '5 seconds', '2 minutes', '4 hours'. '0 seconds' will deactivate slowmode.
    Context: message
  • enable-emergency-mode
    Will toggle emergency mode
    Accepts: A bool (true or false), representing whether emergency mode should be enabled or disabled
    Context: Any

Thread actions

  • archive-thread
    Will archive a thread
    Accepts: Nothing
    Context: message
  • lock-thread
    Will lock a thread
    Accepts: Nothing
    Context: message
  • archive-and-lock-thread
    Will archive and lock a thread
    Accepts: Nothing
    Context: message
  • delete-thread
    Will delete a thread
    Accepts: Nothing
    Context: message

Heat level actions

  • add-user-heatpoint
    Adds a single heat point with the specified lifetime to the user's heat level
    Accepts: A string representing the heat point's lifetime. Some examples: '5 seconds', '2 minutes', '4 hours'
    Context: user
    Example: add-user-heatpoint: 5 seconds add-user-heatpoint: 1m
  • add-user-heatpoints
    Adds multiple heat points with the specified lifetime to the user's heat level
    Accepts: A list containing two elements: the amount of heatpoints to assign (1-100) and a string representing the heat points' lifetime. Some examples: '5 seconds', '2 minutes', '4 hours'
    Context: user
    Example: add-user-heatpoints: [10, 5 seconds] add-user-heatpoints: [2, 1m]
  • add-channel-heatpoint
    Adds a single heat point with the specified lifetime to the channel's heat level
    Accepts: A string representing the heat point's lifetime. Some examples: '5 seconds', '2 minutes', '4 hours'
    Context: message
    Example: add-channel-heatpoint: 5 seconds add-channel-heatpoint: 1m
  • add-channel-heatpoints
    Adds multiple heat points with the specified lifetime to the channel's heat level
    Accepts: A list containing two elements: the amount of heatpoints to assign (1-100) and a string representing the heat points' lifetime. Some examples: '5 seconds', '2 minutes', '4 hours'
    Context: message
    Example: add-channel-heatpoints: [10, 5 seconds] add-channel-heatpoints: [2, 1m]
  • add-custom-heatpoint
    Adds a single heat point with the specified lifetime to the custom heat level
    Accepts: A list containing two elements: a string representing the custom heat level name and a string representing the heat point's lifetime. Some examples: '5 seconds', '2 minutes', '4 hours'. Rule name and IDs context variables are available for the name.
    Context: Any
    Example: add-custom-heatpoint: ["filter-$user_id", "5 seconds"]
  • add-custom-heatpoints
    Adds multiple heat points with the specified lifetime to the custom heat level
    Accepts: A list containing three elements: a string representing the custom heat level name, a number representing the amount of heat points to add and a string representing the heat points lifetime. Some examples: '5 seconds', '2 minutes', '4 hours'. Rule name and IDs context variables are available for the name.
    Context: Any
    Example: add-user-heatpoints: ["$rule_name", 10, 5 seconds]
  • empty-user-heat
    Sets the user's heat level to 0
    Accepts: Nothing
    Context: user
  • empty-channel-heat
    Sets the channel's heat level to 0
    Accepts: Nothing
    Context: message
  • empty-custom-heat
    Sets the specified custom heat level to 0
    Accepts: A string representing the custom heat level name. Rule name and IDs context variables are available for the name.
    Context: Any

Various actions

  • no-op
    Does nothing. Useful only for testing a rule's conditions with [p]defender warden run
    Accepts: Nothing
    Context: Any
  • exit
    Interrupts the rule's processing, not carrying on any further action. This is useful when used in conjunction with conditional actions.
    Accepts: Nothing
    Context: Any
  • issue-command
    Will issue a bot command as if it was issued by the specified user. The specified user must be the rule's author. If no destination is specified issuing a command in a message context will make it issue in the same channel as the message's; in any other case the command will be issued in Defender's notification channel.
    Accepts: A list with two elements: a number representing the ID of the rule's author and a string representing the command to issue. The command must not contain the prefix. Context variables are supported. The long form of this action also supports a destination.
    Context: Any
    Example:
    - issue-command: [2626262626, "ban $user_id User has been banned by Warden's rule $rule_name"]
    - issue-command:
       issue_as: 2626262626 # User ID
       command: ping # Command
       destination: 123456 # Channel ID
    
  • delete-last-message-sent-after
    Will delete the last message sent through a Warden action after the specified time. The time must be between 1 and 15 minutes.
    Accepts: A string representing the time to wait before deleting the message
    Context: Any
    Example: send-message: [$channel_id, I'm going to disappear in 5 seconds!]
    delete-last-message-sent-after: 5 seconds
  • var-assign
    Assigns a value to a variable.
    - var-assign: [my_var, 123]
    - var-assign:
        var_name: my_var
        value: 123
        evaluate: false # (optional, if true any context variable contained in value will be evaluated)
    # The variable my_var will be equal to 123
    
  • var-assign-random
    Assigns a random value to a variable, picking one from a list of choices. Supports weighted choices
    # A simple, non-weighted choice
    - var-assign-random: [my_var, [apple, banana, pear]]
    - var-assign-random:
        var_name: my_var
        choices: [apple, banana, pear]
        evaluate: false # (optional, if true any context variable contained in value will be evaluated)
    # A weighted choice
    - var-assign-random:
        var_name: my_var
        choices:
           apple: 10
           banana: 1
           pear: 2
        evaluate: false # (optional, if true any context variable contained in value will be evaluated)
    
  • var-assign-heat
    Assigns a heat level value to a variable. Supports all kinds of heat levels.
    - add-user-heatpoints: [2, 10 minutes]
    - add-channel-heatpoints: [3, 10 minutes]
    - add-custom-heatpoints: [example, 4, 10 minutes]
    - var-assign-heat: [u_heat, user_heat] # Assigns user's heat to the variable u_heat
    - var-assign-heat: [ch_heat, channel_heat] # Assigns channel's heat to the variable ch_heat
    - var-assign-heat: [cu_heat, example] # Assigns custom heat "example" to the variable cu_heat
    
    - send-to-monitor: "Custom heat level 'example': $cu_heat" # Displays the custom heat level "example"
    
    - var-math: [result, "$u_heat", "+", "$ch_heat"] # Calculates the sum of user heat and channel heat
    - send-to-monitor: "This is the sum of user and channel heat levels: $result"
    
  • var-math
    Allows to perform mathematical operations with up to two operands. Supports context variables.
    Supported operators: +, -, *, /, pow, abs, floor, ceil, trunc
    - var-math: [re, 1, "+", 1] # var re equals to 2
    - var-math: [re, 2, "*", 3] # var re equals to 6
    - var-math: [re, -5, "abs"] # var re equals to 5
    - var-math: [re, 5.1, "ceil"] # var re equals to 6
    - var-math: [re, 2.26, "trunc"] # var re equals to 2
    
    - var-assign: [op1, 52]
    - var-assign: [op2, 2]
    - var-math: [re, "$op1", "/", "$op2"] # var re equals to 26.0
    
  • var-split
    Splits a variable into parts, using separator as the delimiter, and assigns the parts to different variables. If there are more parts than provided variables, the remaining parts will be discarded. If there are fewer parts than provided variables, an empty string will be assigned to the remaining variables. Maximum splits can be specified, by default there is no limit.
    - var-assign: [fruit, "apple pear banana tomato"]
    
    # fruit1 will contain "apple", fruit2 "pear", etc. Splits are done left to right.
    - var-split: [fruit, " ", [fruit1, fruit2, fruit3, fruit4]]
    
    # As before fruit1 will contain "apple", fruit2 "pear" but the remaining parts will be lost
    - var-split: [fruit, " ", [fruit1, fruit2]]
    
    # A max_split of 1 is specified, fruit1 will still be "apple", but fruit2 will be "pear banana tomato"
    - var-split: [fruit, " ", [fruit1, fruit2], 1]
    - compare: ["$fruit2", "==", "pear banana tomato"] # True!
    
    # Same as before, but fruit3 will be an empty string: only one split has been done, and there's nothing left to assign to fruit3.
    - var-split: [fruit, " ", [fruit1, fruit2, fruit3], 1]
    - compare: ["$fruit1", "==", "apple"] # True!
    - compare: ["$fruit3", "==", ""] # True!
    
    # Long form:
    - var-split:
        var_name: fruit
        separator: " "
        split_into: [fruit1, fruit2, fruit3]
        max_split: 1 # (optional)
    
  • var-slice
    Slices a variable according to the indices (the position of the characters) that are being passed. If a variable name is passed with slice_into the original variable will be left untouched. The optional parameter step, found in Python's string slicing, can also be passed. Remember than indices start from 0, not 1.
    - var-assign: [my_var, "abcdefgh"]
    - var-slice: [my_var, 0, 2, sliced]
    - compare: ["$sliced", "==", "ab"] # True!
    
    - var-slice: [my_var, 0, 4]
    - compare: ["$my_var", "==", "abcd"] # True!
    
    - var-assign: [my_var, "abcdefgh"]
    # Long form
    - var-slice:
        var_name: my_var
        index: 0
        end_index: 99
        slice_into: sliced
        step: 2
    - compare: ["$sliced", "==", "aceg"] # True!
    
  • var-replace
    Modifies a variable with all the occurrences of strings replaced by substring. Strings can be a single value or a list of values.
    - var-assign: [my_var, "I like apples a lot"]
    - var-replace: [my_var, a, 4]
    - compare: ["$sliced", "==", "I like 4pples 4 lot"] # True!
    
    - var-assign: [my_var, "I like apples a lot"]
    - var-replace: [my_var, [a, p], x]
    - compare: ["$sliced", "==", "I like xxxles x lot"] # True!
    
    # Long form
    - var-replace:
        var_name: my_var
        strings: a # Can also be a list, as shown above
        substring: b
    
  • var-transform
    Modifies a variable depending on the "operation" that it's being requested. Supported operations are capitalize, lowercase, reverse, uppercase, title.
    - var-assign: [my_var, "I like apples A LOT"]
    - var-transform: [my_var, lowercase]
    - compare: ["$my_var", "==", "i like apples a lot"] # True!
    
    - var-transform: [my_var, uppercase]
    - compare: ["$my_var", "==", "I LIKE APPLES A LOT"] # True!
    
    - var-assign: [my_var, "I like apples a lot"]
    - var-transform: [my_var, title] # Capitalizes the first letter of each word
    - compare: ["$my_var", "==", "I Like Apples A Lot"] # True!
    
    - var-assign: [my_var, "two words"]
    - var-transform: [my_var, capitalize] # Only capitalizes the first letter
    - compare: ["$my_var", "==", "Two words"] # True! 
    
    # Long form
    - var-transform:
        var_name: my_var
        operation: uppercase