Introduction
NOTE: Just adding AntiRaid (or any discord bot) to your server will not do much unless you configure it first!
AntiRaid is a discord bot that takes a very unique approach to protecting servers. Instead of providing a single-size-fits-all solution, AntiRaid makes use of "structured templating" and a (work in progress/coming soon) template shop to allow servers to protect themselves in a way that is tailored to them.
Our Philosophy
While many bots like Wick provide a managed anti-raid/anti-nuke solution, these systems often provide suboptimal user experience to many servers as they may not cater to specific needs of the server. Wick, for example, is often criticized for limiting the abilities of server moderators in a way that makes moderation harder. While Wick is useful in many servers and does work quite well in the anti-raid/anti-nuke field from our experience, it may not be the best solution for all servers.
Templating, on the other hand, allows servers to tailor their needs directly without needing to go through the pain of making a custom discord bot, hosting it and then navigating the complexities of the discord API manually while reinventing concepts like stings/punishments/permissions/captchas all over again.
Permissions
Imagine. Imagine a discord bot that you could completely control. You could decide who can use any specific command, who can change the bot's settings, and who can even use the bot at all.
Thats AntiRaid...
AntiRaid has a customizable permission system that uses both Discord permissions for simplicity and kittycat permissions for more specific requirements. While AntiRaid does provide some base-line defaults, Lua scripting can be used to augment these defaults and extend Antiraid with arbitrarily complex permission systems, among other things. See the templating guide for more information on how to use Lua templates. Then, just code away!
TIP
For best results, consider limiting the server permissions of other users to the minimum required. Then, use AntiRaid for actual moderation. That's better than giving everyone admin permissions and then trying to restrict them with AntiRaid.
Templating
At AntiRaid, we prioritize flexibility and customization for our users. To this end, our bot supports advanced templating to allow for extensive personalization of embeds and messages. While many bots utilize proprietary languages or templating engines, we have chosen to leverage Lua—a renowned scripting language widely used in game development and other applications. This decision ensures that our users benefit from a powerful, well-documented, and versatile language, enhancing the capability and ease of customizing their AntiRaid experience.
Note: this documentation is still a work-in-progress and things are still being documented better and better by the day!
Loading templates from the shop
You can use the /load
command to load templates from the shop.
Captcha
Introduction
WARNING: Captcha's are being heavily churned/rewritten into a new Lua plugin
A CAPTCHA is a security measure that can be used to try and filter out the more basic and spammy bots from accessing your server. It presents a challenge that users must complete to prove they are human. This can help protect your server from unwanted automated access and ensure that real users can interact with your community. Note that CAPTCHA's are NOT foolproof and that more sophistiated bots may still bypass them.
Of course, with the current landscape with AI everywhere, just serving a single CAPTCHA type (or config) does not really work. Furthermore, AntiRaid recognizes that different servers have different needs. Therefore, we provide a flexible CAPTCHA system, fully integrated with our Lua Templating system that allows you to completely customize the CAPTCHA experience for your users. This occurs through filters.
Examples
Sample CAPTCHA
local interop = require "@antiraid/interop"
local img_captcha = require "@antiraid/img_captcha"
local captcha_config = {}
-- Basic options
captcha_config.char_count = 7
captcha_config.filters = {}
setmetatable(captcha_config.filters, interop.array_metatable) -- Filters is an array
captcha_config.viewbox_size = { 280, 160 }
setmetatable(captcha_config.viewbox_size, interop.array_metatable) -- Viewbox size is a tuple
-- Add noise filter
local noise_filter = {
filter = "Noise",
prob = 0.05
}
table.insert(captcha_config.filters, noise_filter)
-- Add wave filter
local wave_filter = {
filter = "Wave",
f = 4.0, -- Frequency
amp = 20.0, -- Amplitude
d = "horizontal" -- Direction
}
table.insert(captcha_config.filters, wave_filter)
-- Add grid filter
local grid_filter = {
filter = "Grid",
x_gap = 10,
y_gap = 30
}
table.insert(captcha_config.filters, grid_filter)
-- Add line filter
local line_filter = {
filter = "Line",
p1 = setmetatable({ 0.0, 0.0 }, interop.array_metatable),
p2 = setmetatable({ 30.0, 100.0 }, interop.array_metatable),
thickness = 7.0,
color = setmetatable({ 0, 0, 0 }, interop.array_metatable)
}
table.insert(captcha_config.filters, line_filter)
-- Add color invert filter
local color_invert_filter = {
filter = "ColorInvert"
}
table.insert(captcha_config.filters, color_invert_filter)
-- Add random line filter
local random_line_filter = {
filter = "RandomLine"
}
table.insert(captcha_config.filters, random_line_filter)
local captcha = img_captcha.new(captcha_config)
return captcha
CAPTCHA with increasing char count with maximum of 5 tries per user
=local interop = require "@antiraid/interop"
local img_captcha = require "@antiraid/img_captcha"
local captcha_config = {}
-- Check __stack.users
if __stack._captcha_user_tries == nil then
__stack._captcha_user_tries = {} -- Initialize users table
end
-- Check __stack._captcha_user_tries[args.user.id]
if __stack._captcha_user_tries[args.user.id] == nil then
__stack._captcha_user_tries[args.user.id] = 0 -- Initialize user's try count
end
-- Check if user has reached maximum tries
if __stack._captcha_user_tries[args.user.id] >= 5 then
error("You have reached the maximum number of tries in this 5 minute window.")
end
-- Basic options
captcha_config.char_count = math.min(7 + __stack._captcha_user_tries[args.user.id], 10) -- Increment the number of characters
captcha_config.filters = {}
setmetatable(captcha_config.filters, interop.array_metatable) -- Filters is an array
captcha_config.viewbox_size = { 280, 160 }
setmetatable(captcha_config.viewbox_size, interop.array_metatable) -- Viewbox size is a tuple
-- Increment the maximum number of tries
__stack._captcha_user_tries[args.user.id] += 1
captcha = img_captcha.new(captcha_config)
return captcha
Lockdowns
Lockdowns are a way to allow restricting (or 'locking down') specific channels or roles within a server when under an attack or other such crises.
Migrating from other bots
If you are coming from Wick or another anti-nuke bot like Wick, please note that AntiRaid's lockdown functionality only applies to locking down channels and roles. This means that the following Wick features are not present in AntiRaid lockdowns and are instead part of other more appropriate modules as listed below:
- Join Auto Kick (present in Inspector Auto Response Member Join)
- Join Auto Ban (present in Inspector Auto Response Member Join)
- Role Lockdown (WIP, not yet implemented)
- All / Server Wide (Most likely will not be implemented)
Note that blind lockdowns are not yet implemented in Anti-Raid.
For the sake of comparisons, here is how each lockdown mode compares to Wick's lockdown modes:
- Quick Server Lockdown (
qsl
) -> Wick's Channels (sc
) lockdown (general performance+requirements for use should be the same as Wick's lockdown feature) - Traditional Server Lockdown (
tsl
) -> No equivalent in Wick - Single-Channel Lockdown (
scl
) -> Wick's Channel (c
) lockdown (note that locking down multiple specific channels at once is not yet implemented in AntiRaid)
Usage Notes
If you want to know more details on each type of lockdown, how they are applied and how multiple lockdown conflicts are resolved, please refer to the dev docs for lockdown
Member Roles
When you first setup lockdown for the first time, you will be prompted for a set of member roles like below:
These roles are what AntiRaid will actually lock-down which is why they are also known as 'critical roles'.
Quick Server Lockdowns
For servers that can meet its restrictions, a quick server lockdown is the fastest way to lockdown your server in a raid. It is recommended to use this lockdown mode if possible. When using this mode, it is important to note one critical requirement:
- All critical roles must have View Channel and Send Messages. All other roles must not have View Channel and Send Messages.
What this looks like is something like the following:
Figure 1 shows a normal role without View Channel of Send Messages permissions
Figure 2 shows a critical role with View Channel and Send Messages permissions
The above two figures are how you want to configure your critical/member and normal roles. Basically, turn off View Channel and Send Messages for all your normal roles and turn it on for your critical/member roles you set up earlier in the settings for lockdown.
To make a quick server lockdown, you can use the qsl
type. For example, to lock down a server, you can use the following slash command:
/lockdown lock type:qsl reason:There is a raid going on
Traditional Server Lockdown
Traditional Server Lockdown is a more traditional lockdown method. It is more flexible than Quick Server Lockdown as it has no required prior setup. However, it is much slower and should be avoided if possible.
WARNING: Super large servers may have outages when using a traditional server lockdown that a quick server lockdown may not lead to.
To make a traditional server lockdown, you can use the tsl
type. For example, to lock down a server, you can use the following slash command:
/lockdown lock type:tsl reason:There is a raid going on
Single-Channel Lockdown
In some cases, only a single channel needs to be locked down. In such a case, a single-channel lockdown is needed.
To make a single-channel lockdown, you can use the scl
type. For example, to lock down a server, you can use the following slash command:
/lockdown lock type:scl/<channel_id> reason:There is a raid going on
Where <channel_id>
is the ID of the channel to lockdown.
Backups
What's backed up
Guild structure (roles/channels/name/icon/other settings), some messages (Discord has limits here) and attachments (within reasonable limits).
What's not backed up?
Members and bots. Note that for members, we have something coming up soon that may allow you to 'backup/restore' (with consent + regularly re-providing consent) members.
Note that new discord features may also not be backed up/restored immediately on release.
More details
See the dev guide to learn more about the format
Go Jobserver
The Go Jobserver handles server backups, message prunes and other long running tasks on a server
Backups
Note that this document describes the technical details of the backup system
Format
A backup is an https://github.com/infinitybotlist/iblfile with the standard AutoEncryptedFile
format and has the following fields:
backup_opts
- JSON containing atypes.BackupCreateOpts
objectcore/guild
- The core guild data (discordgo.Guild
)assets/{asset_name}
- The guild icon data ([]byte
)messages/{channel_id}
- The messages in a channel along with basic attachment metadata ([]types.BackupMessage
).dbg/*
- Debug information. This may vary across backups and MUST NOT be used in restoring a backup.attachments/{attachment_id}
- The attachments data itself
Silverpelt
Anti-Raid Templating System
Supported Languages
- Lua (luau / Roblox Lua) - Tier 1
Lua is the recommended language for templating
WIP/Potential Languages
- JavaScript (see
lang_javascript_quickjs
andlang_javascript_v8
for the current load experiments + integration experiments), potential but unlikely unless someone finds a solution - WebAssembly (potential, not yet decided)
Language Requirements
- All languages must export the following modules/helpers to the extent required as per the templating documentation. (TODO: Improve this spec)
- Messages
- Permissions
- Captcha
- Actions
- Key Value API
- All languages must provide a way to sandbox the execution of the code. This is a security requirement. In particular, timeouts and heap/stack/memory limits are required.
- Callers must use the abstracted out function calls from
lib.rs
My language vent
For reference on my discord vents: https://discord.com/channels/763812938875535361/1040734156327501905/1267195190100361440
Why is lua the only sane language for embedding V8 has big ffi problems with rust. If you try spawning too many isolates, you have a 100% chance of aborting your process and this issue can only be resolved by performing unsafe void* pointer casts Quickjs is a bit too slow and poorly documented Rhai is good but it’s a custom language and it’s sandboxing abilities need unsafe code to fully work (and said unsafe code involves pointer arithmetic that is not thread safe) and heap memory limits require you to manually calculate the heap usage Tera has virtually no safety features and will gladly execute an infinite recursion For starlark/skylark, go to the point on rhai but hopefully without the unsafe bits I can understand now why the game modding industry uses lua, it’s basically the only sane language for handling user input Lua is legit the only sane scripting language on this entire list
[rhai is not only slower than lua, its sandboxing (i said it above here too in a vent i think) requires actual pointer arithmetic that isnt thread safe, its also a custom lang no one knows while lua is well known in the game community. Luau is used in Roblox games so it caters to Discords target market as well]
Template Tokens
All lua templates include a special template token in addition to the template arguments. Modules requiring more privileged levels of access (or otherwise require the template state) should require this token and use it to access the required template state.
Lua Templating
At AntiRaid, we prioritize flexibility and customization for our users. To this end, our bot supports advanced templating to allow for extensive personalization of embeds and messages. While many bots utilize proprietary languages or templating engines, we have chosen to leverage Lua—a renowned scripting language widely used in game development and other applications. This decision ensures that our users benefit from a powerful, well-documented, and versatile language, enhancing the capability and ease of customizing their AntiRaid experience.
Specifically, Anti Raid uses a variant of Lua called Luau. If you've ever used Roblox before, this is the same variant of Lua used there too (which is why Luau is also known as Roblox Lua in many places). You can check out the Luau docs for more information on the language itself. Unlike PUC Lua (the reference implementation), Luau is both faster and offers robust sandboxing capabilities allowing AntiRaid to run scripts in as safe an environment as possible.
Getting Started
Note that the remainder of these docs will cover AntiRaids Lua SDKs. To learn more about Lua itself, please checkout Lua's official tutorial for Lua 5.0 here. Other resources for Lua exist (Lua is very popular after all), including Roblox's tutorial (ignore the Studio bits), TutorialPoint and Codecademy.
Limitations
AntiRaid applies the following 3 global limits to all Lua templates. Note that we may provide increased limits as a Premium feature in the future:
#![allow(unused)] fn main() { pub const MAX_TEMPLATE_MEMORY_USAGE: usize = 1024 * 1024 * 3; // 3MB maximum memory pub const MAX_TEMPLATES_EXECUTION_TIME: std::time::Duration = std::time::Duration::from_secs(30); // 30 seconds maximum execution time }
The above limits are in place to prevent abuse and ensure that the bot remains responsive. If you require increased limits, please contact support (once again, this may change in the future).
Some key notes
- Each guild is assigned a dedicated Lua(u) VM. This VM is used to execute Lua code that is used in the templates.
- The total memory usage that a guild can use is limited to
MAX_TEMPLATE_MEMORY_USAGE
(currently 3MB). This is to prevent a single guild from using too much memory. - Execution of all scripts is timed out when the last executed script takes longer than
MAX_TEMPLATES_EXECUTION_TIME
(currently 30 seconds). - A guilds Lua(u) VM will persist until marked as broken (either by explicitly requesting it or by exceeding memory limits)
- While a guilds Lua(u) VM will internally have a read-only shared global table, AntiRaid provides a special global table that is isolated at the template level with a custom
__index
and__metatable
set to proxy writes (similar to Roblox's setup). This means that builtins will remain read-only, but new values can be added. - The standard
require
statement can be used to either import AntiRaid plugins or to import other Luau assets that belong to the template. AntiRaid internally uses standard Luau require-by-string semantics with support forinit.luau
files for requires. - Note that plugins are read-only/sandboxed and cannot be monkey-patched etc.
- All templates are executed as Luau threads.
In general, all AntiRaid templates should start with the following:
local evt, token = ...
-- Do something
return output -- Optionally return something here
Interop
Many features of Lua don't work so well when calling functions within the AntiRaid SDK. For example, both arrays and maps are expressed as tables in Lua. However, AntiRaid, being written in Rust, doesn't know this and hance needs some help to convert certain types for FFI. This is where the @antiraid/interop
module comes in.
Arrays
To pass arrays to modules within the AntiRaid SDK, you need to set the metatable to @antiraid/interop#array_metatable
. This will allow the SDK to convert the array to a Rust Vec
internally.
local interop = require '@antiraid/interop'
setmetatable({a = 5}, interop.array_metatable)
Null
In some instances, interactions with AntiRaid may yield a special null
lightuserdata value. This lightuserdata value is exposed under @antiraid/interop#null
and can also be used template-side as desired:
local interop = require '@antiraid/interop'
local null = interop.null -- This is the null value
Memory Usage
While not strictly useful for interop, it is often desirable to know the memory usage of a Lua template as AntiRaid will kill your template if it exceeds the memory limit. For this, you can use the @antiraid/interop#memusage
function.
local interop = require '@antiraid/interop'
print(interop.memusage())
Events
All Lua templates are invoked via events. As such, the first argument to the template is an Event
. Event
is a userdata
. The below will explain the most important fields exposed by Event
. Note that all fields, unless stated otherwise, are read-only and cached.
Template Context
All Lua templates are passed both the Event
(denoted by args
) and a TemplateContext
userdata (denoted by token
). Note that like Event
, TemplateContext
is a userdata (not a table). As such, they cannot be manually constructed in templates themselves.
"Executors" and other sensistive APIs use the TemplateContext
to read internal data. Examples of executors include the @antiraid/discord
DiscordActionExecutor
, which allows you to perform actions such as banning/kicking/timing out users and other Discord actions and @antiraid/kv
KvExecutor
which allow for persistent storage via a key-value interface.
TemplateContext
is guaranteed to be valid while accessible in the VM . This means that templates can choose to share their capabilities with other templates using _G
.
Likewise, it is also guaranteed that the created executor is complete and does not rely on the token itself whatsoever after creation. This means that a template executor can be used after the template has finished executing (e.g. in a coroutine).
Example
local args, token = ...
print(token)