Advanced scripting

Using Rhai language for programming complex actions

On top of vSL predefined actions, users can define complex rules using the Rhai scripting language.

action "let example" || {
    let my_string = "The question is 7x6 = 42 ?";
    // ... do stuff

    log("error", `I'm writing this string : ${my_string} as an error`);
};

Rhai functions can be declared and used in vSL.

fn my_condition() {
    let my_int = if client_ip() == "192.168.1.34" { 42 } else { 0 };

    if (my_int == 42) {
        true
    } else {
        false
    }
}

fn my_action1() {
    log("warn", "Ok - coming from localhost");
    next()
}

fn my_action2(rcpts) {
    let admin = "admin@foobar.com";
    log("error", `Not from localhost. Logging the recipients's list: ${rcpts}`);

    for rc in rcpts {
      log("debug", `  - ${rc}`);
    }

    next()
}


#{
    // ... other rules.
    rcpt: [
        rule "rcpt log" || { if my_condition() { my_action1() } else { my_action2(rcpt_list()) } },
    ]
}

✎ | Rhai’s function are “pure”, they do not capture their external scope. Variables must be passed as arguments.

Importing user defined modules

External modules can be imported in the main.vsl file.

Rhai functions are automatically exported. Therefore do not forget to add the private keyword for internal functions. Unlike functions, variables are not exported. You must do it manually using the export keyword. Check out the Rhai Book for more information.

Example :

// -- mod/my_module.vsl
fn my_function() {
    let z = add_function(24);
    // ... do stuff.
}

private fn add_function(v) {
    return v + 42;
}

export const x = 42;
// -- main.vsl
import "mod/my_module" as my_mod;

my_mod::my_function();
print(my_mod::x);

// add_function(33) -> won't work because `add_function` is private.