Scripting
General Info
Permissions - perms on scripts are weird and their names do not necessarily betray their entire scope of influence. For example, all of my scripts that make http requests even to LAN endpoints require the ftp permission in order to run.
Examples
Sending a message in Discord via webhook
:local webhookUrl \"https://discord.com/api/webhooks/_redacted_/redacted\"
:local message \$1
:local jsonPayload (\"{\\\"content\\\":\\\"\$message\\\"}\")
/tool fetch url=\$webhookUrl http-method=post http-data=\$jsonPayload http-header-field=\"Content-Type: application/json\" keep-result=no
Example usage (my DHCP lease script)
# DHCP Lease Script
# This script is intended to be run by the DHCP server on-lease event.
# Define the message content using built-in DHCP server variables
:local messageToSend ("New DHCP Lease Assigned:\nIP: $leaseActIP\nMAC: $leaseMAC\nHostname: $leaseHostName")
# Run the webhook script, passing the message as an argument
/system script run send_discord_webhook message=$messageToSend
Attention
I’ve had issues with passing arguments to scripts like this with different versions of RouterOS before. If this doesn’t work for you, you can write the message you want to send to a global variable and then call the discord webhook script (which would need modified to load the message to send from the same global variable)
This is basically the same thing as the Discord webhook but with some examination of the JSON response from the endpoint
:log info "RVLink WAN Check (Open Network, All POST): Starting script."
:local mv2402ip "192.168.10.254"
:local targetSsid "NittanyMtnKOA"
# Step 1: Check Wi-Fi Status (via guide_config, using POST)
:local statusUrl "http://$mv2402ip/cgi-bin/mbox-config?method=GET§ion=guide_config"
:local statusResponse
:local isConnectedToTarget false
:do {
:log info "Attempting to fetch status from $statusUrl"
# Fixed fetch command with proper headers format
:set statusResponse [ /tool fetch url=$statusUrl http-method=post \
http-data="{}" \
http-header-field="Content-Type: application/json, Accept: */*" \
as-value ]
# Detailed logging for debugging
:log info ("GuideConfig Fetch Details: Status=" . ($statusResponse->"status") . \
", HTTP_Status=" . ($statusResponse->"status-code"))
# Check if we got a successful response
:if ($statusResponse->"status" = "finished") do={
:local responseData ($statusResponse->"data")
#:log info ("Response data: " . $responseData)
# Simple string search to check if target SSID is in the response
:if ([:find $responseData $targetSsid] != "") do={
:set isConnectedToTarget true
:log info "RVLink WAN Check: SUCCESS - Currently connected to $targetSsid"
} else {
:log warning "RVLink WAN Check: Not connected to target SSID"
}
} else {
:log error ("RVLink WAN Check: Failed to get Wi-Fi status. Error: " . ($statusResponse->"error"))
}
} on-error={
:log error "RVLink WAN Check: Critical script exception during Wi-Fi status check phase."
}
Info
This isn’t doing any actual JSON parsing. For the purpose of this script it’s enough that the value of the target SSID appears in the response (indicating that the roof unit is associated to the target wireless network)
Sample response for the endpoint being requested, for context
{
"errMsg": "OK",
"errCode": 0,
"wwan": {
"ssid": "NittanyMtnKOA",
"encryption": "none",
"device": "radio0",
"bssid": "44:D1:FA:1D:D6:37",
"wan_dns2": "",
"wan_iface": "wan",
"wan_ifname": "vif-sta0",
"key": "",
"wan_netmask": 23,
"wan_dns1": "192.168.18.1",
"wan_dhcp_lease_time": 7200,
"wan_gateway": "192.168.18.1",
"wan_ip": "192.168.18.70"
},
"lan": {
"gateway": "",
"leasetime": "86400",
"ipaddr": "192.168.10.254",
"start": "100",
"netmask": "255.255.255.0",
"limit": "100",
"domain": "COMFAST",
"ignore": ""
}
}
The ssid field value is what we’re looking for using the :find function in the script above. Which is pulled directly from the live configuration of the device using uci.