Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/AresChat/sb0t/llms.txt

Use this file to discover all available pages before exploring further.

sb0t injects a collection of singleton objects into every script engine alongside the global functions. These objects expose server state and utilities as simple property/method APIs. They are available at any time — inside event handlers, onTimer, or top-level script code — with no import needed.

Room

Provides access to room-level configuration and broadcast helpers. Backed by JSRoom.cs.

Properties

PropertyTypeAccessDescription
Room.versionnumberread-onlyCurrent scripting API version integer (e.g. 5009).
Room.botNamestringread-onlyThe display name of the room bot.
Room.customNamesbooleanread/writeWhether custom display names (user.customName) are enabled for the room.
Room.externalIpstringread-onlyThe server’s external IP address as a string.
Room.hashlinkstringread-onlyAn arlnk:// prefixed hashlink for this room.
Room.namestringread-onlyThe room name.
Room.portnumberread-onlyThe port the server is listening on.
Room.startTimenumberread-onlyUnix-style timestamp (server time) of when the room started.
Room.topicstringread/writeThe room topic. Assign to update it for all users.

Methods

Room.setUrl(addr, text)

Set the room’s shared URL, displayed to all users.
addr
string
The URL address.
text
string
The link display text.
If both arguments are empty or null, the URL is cleared.

Room.clearUrl()

Clear the room’s shared URL.
function onLoad() {
    Room.topic = "Welcome! Type /help for commands.";
    Room.setUrl("https://example.com", "Visit our website");
}

Users

Provides iteration over user pools. Backed by JSUsers.cs.

Methods

Each method accepts a callback function that receives a user (or banned user / record) object for every entry in the pool. Iteration is synchronous.

Users.local(fn)

Iterate over all locally connected users (Ares and web clients on this server instance).
fn
function(user: JSUser)
Called once per local user.

Users.linked(fn)

Iterate over all users connected through linked leaf servers. Only available when the server is linked.
fn
function(user: JSUser)
Called once per linked user.

Users.banned(fn)

Iterate over the current ban list.
fn
function(banned: JSBannedUser)
Called once per ban entry. The JSBannedUser object has: name, version, guid, externalIp, localIp, port (all read-only), and an unban() method.

Users.records(fn)

Iterate over session records (connection history).
fn
function(record: JSRecord)
Called once per record. The JSRecord object has: name, externalIp, localIp, version, port, guid, dns, joinTime (all read-only), and a ban() method.
function onCommand(user, cmd, target, args) {
    if (cmd === "count") {
        var count = 0;
        Users.local(function(u) { count++; });
        print(user, "Local users: " + count);
    }

    if (cmd === "listbans" && user.level >= 2) {
        Users.banned(function(b) {
            print(user, b.name + " (" + b.externalIp + ")");
        });
    }
}

Provides access to the hub link and connected leaf servers. Backed by JSLink.cs.

Properties

PropertyTypeAccessDescription
Link.linkedbooleanread-onlytrue if this server is currently linked to a hub.
Link.namestring | nullread-onlyThe room name of the hub, or null if not linked.
Link.externalIpstring | nullread-onlyExternal IP of the hub, or null if not linked.
Link.portnumberread-onlyPort of the hub connection, or -1 if not linked.
Link.hashlinkstring | nullread-onlyAn arlnk:// hashlink for the hub room, or null if not linked.

Methods

Iterate over all currently connected leaf servers.
fn
function(leaf: JSLeaf)
Called once per connected leaf.
Find a specific leaf server by name or name prefix.
name
string
The leaf name to search for.
Returns: JSLeaf | null Initiate a link connection to the specified hub address.
address
string
The hub address string.
Disconnect from the current hub.

JSLeaf object

Leaf objects are passed to onLeafJoin, onLeafPart, onLinkedAdminDisabled, and returned by Link.leaf() / Link.leaves().
PropertyTypeDescription
leaf.namestringThe leaf’s room name.
leaf.externalIpstringThe leaf’s external IP.
leaf.portnumberThe leaf’s port.
leaf.hashlinkstringAn arlnk:// hashlink for the leaf room.
MethodDescription
leaf.print(text)Send a system message to all users on the leaf.
leaf.print(vroom, text)Send to a specific vroom on the leaf.
leaf.printAdmins(level, text)Send to users at or above level (1=mod, 2=admin, 3=host) on the leaf.
leaf.users(fn)Iterate over users on this leaf.
leaf.user(name)Find a user on this leaf by name or name prefix. Returns JSUser | null.
leaf.sendText(sender, text)Broadcast a public chat line to the leaf.
leaf.sendEmote(sender, text)Broadcast an emote line to the leaf.
leaf.scribble(image[, sender])Send a scribble image to all users on the leaf. image is a JSScribbleImage; sender defaults to Room.botName.
function onLeafJoin(leaf) {
    print("Leaf connected: " + leaf.name + " (" + leaf.hashlink + ")");
}

function onCommand(user, cmd, target, args) {
    if (cmd === "leafusers") {
        var l = Link.leaf(args);
        if (!l) { print(user, "Leaf not found."); return; }
        l.users(function(u) { print(user, u.name); });
    }
}

Crypto

Hashing utilities. Backed by JSCrypto.cs.

Methods

Crypto.md5hash(text)

Compute an MD5 hash of the UTF-8 encoded text.
text
string
The input string.
Returns: JSCryptoResult | null

Crypto.sha1hash(text)

Compute a SHA-1 hash of the UTF-8 encoded text.
text
string
The input string.
Returns: JSCryptoResult | null

JSCryptoResult object

MethodReturnsDescription
result.toHex()stringUppercase hex representation of the hash bytes (e.g. "5D41402ABC4B2...")
result.toBase64()stringBase64 encoded representation of the hash bytes.
result.toArray()Array<number>Array of byte integers.
function onCommand(user, cmd, target, args) {
    if (cmd === "md5") {
        var hash = Crypto.md5hash(args);
        print(user, "MD5: " + hash.toHex());
    }
}

Stats

Read-only server statistics. Backed by JSStats.cs.
PropertyTypeDescription
Stats.userCountnumberCurrent number of connected users.
Stats.peakUserCountnumberPeak simultaneous user count since the server started.
Stats.joinCountnumberTotal join events since the server started.
Stats.partCountnumberTotal part events since the server started.
Stats.rejectionCountnumberTotal rejected connection attempts.
Stats.messageCountnumberTotal public messages sent.
Stats.pmCountnumberTotal private messages sent.
Stats.floodCountnumberTotal flood events triggered.
Stats.invalidLoginCountnumberTotal failed admin login attempts.
Stats.dataReceivednumberTotal bytes received by the server.
Stats.dataSentnumberTotal bytes sent by the server.
function onCommand(user, cmd, target, args) {
    if (cmd === "stats") {
        print(user, "Users: " + Stats.userCount + " (peak: " + Stats.peakUserCount + ")");
        print(user, "Messages: " + Stats.messageCount + ", PMs: " + Stats.pmCount);
    }
}

File

Sandboxed file I/O scoped to the script’s own data/ subfolder. Backed by JSFile.cs. All file operations are restricted to %AppData%\sb0t\<app-name>\Scripting\<scriptName>\data\. Filenames must not contain .., /, \, or spaces.

Methods

File.load(filename)

Read the entire contents of a file as a UTF-8 string.
filename
string
The filename inside the data/ folder.
Returns: string | null — file contents, or null if the file does not exist or on error.

File.save(filename, content)

Write (overwrite) a file with the given content, encoded as UTF-8. Creates the data/ folder if it does not exist.
filename
string
Target filename.
content
string
The content to write.
Returns: booleantrue on success.

File.append(filename, content)

Append content to a file. Creates the file and data/ folder if they do not exist.
filename
string
Target filename.
content
string
The content to append.
Returns: booleantrue on success.

File.exists(filename)

Check whether a file exists in the data/ folder.
filename
string
The filename to check.
Returns: boolean

File.kill(filename)

Delete a file from the data/ folder.
filename
string
The filename to delete.
Returns: booleantrue if the file was deleted.
function onLoad() {
    if (!File.exists("config.txt")) {
        File.save("config.txt", "greeting=Hello!\n");
    }
    var cfg = File.load("config.txt");
    print("Config loaded: " + cfg);
}

Channels

Access to the Ares channel directory. Backed by JSChannels.cs.

Properties

PropertyTypeDescription
Channels.availablebooleanWhether the channel list has been fetched and is available.
Channels.enabledbooleanWhether the channel listing feature is enabled on this server.

Methods

Channels.search(query)

Search the channel list for rooms whose name contains query (case-insensitive). Returns at most 10 results with fewer than 200 users, sorted by user count descending.
query
string
Search string.
Returns: JSChannelCollection — an iterable collection of JSChannel objects. Each channel has a name property and a users property (user count).
function onCommand(user, cmd, target, args) {
    if (cmd === "find") {
        var results = Channels.search(args);
        results.forEach(function(ch) {
            print(user, ch.name + " (" + ch.users + " users)");
        });
    }
}

Base64

Base64 encode and decode strings. Backed by JSBase64.cs.

Methods

Base64.encode(text)

Encode a UTF-8 string to Base64.
text
any
The value to encode. null / undefined returns null.
Returns: string | null

Base64.decode(text)

Decode a Base64 string back to UTF-8.
text
string
A valid Base64 string.
Returns: string | null — decoded string, or null on invalid input.
var encoded = Base64.encode("Hello, world!");  // "SGVsbG8sIHdvcmxkIQ=="
var decoded = Base64.decode(encoded);           // "Hello, world!"

Zip

String compression via the server’s compression provider. Backed by JSZip.cs.
The Zip object operates on raw binary-encoded strings via Encoding.Default. It is primarily useful for compressing data before storing it with File.save() or transmitting it through an HTTP request.

Methods

Zip.compress(text)

Compress a UTF-8 string and return the result as a binary-encoded string.
text
any
The input text.
Returns: string | null

Zip.uncompress(text)

Decompress a binary-encoded compressed string back to UTF-8.
text
any
The compressed binary string.
Returns: string | null

Registry

Persistent key/value storage backed by the Windows Registry under HKCU\Software\sb0t\<app-name>\scripting\<scriptName>. Backed by JSRegistry.cs. Values are stored as strings; numeric values are coerced to strings automatically.
Registry storage is scoped per-script. Each script can only read and write its own keys. No cross-script Registry access is possible.

Methods

Registry.exists(key)

Check if a registry key exists for this script.
key
string
Key name.
Returns: boolean

Registry.getValue(key)

Retrieve the stored string value for a key.
key
string
Key name.
Returns: string | null — the stored value, or null if not found.

Registry.setValue(key, value)

Write a string, number, or double value under the given key.
key
string
Key name.
value
string | number
The value to store.
Returns: booleantrue on success.

Registry.deleteValue(key)

Delete a specific key.
key
string
Key name.
Returns: booleantrue if the key existed and was deleted.

Registry.getKeys()

Retrieve all key names stored for this script. Returns: JSRegistryKeyCollection — an iterable collection of key name strings.

Registry.clear()

Delete all stored keys for this script. Returns: booleantrue on success.
function onLoad() {
    if (!Registry.exists("joinCount")) {
        Registry.setValue("joinCount", 0);
    }
}

function onJoin(user) {
    var n = parseInt(Registry.getValue("joinCount"), 10) + 1;
    Registry.setValue("joinCount", n);
}

Encode and decode Ares arlnk:// hashlinks. Backed by JSHashlink.cs.

Methods

Encode a room descriptor object into an arlnk:// hashlink string.
obj
object
A plain JS object with three properties:
  • ip (string) — the room’s IP address.
  • port (number) — the room’s port.
  • name (string) — the room name.
Returns: string | null — the arlnk:// encoded string, or null on failure. Decode an arlnk:// hashlink into its components.
The hashlink string to decode (with or without the arlnk:// prefix).
Returns: JSHashlinkResult | null

JSHashlinkResult object

PropertyTypeDescription
result.namestringRoom name.
result.ipstringRoom IP address.
result.portnumberRoom port.
var link = Hashlink.encode({ ip: "1.2.3.4", port: 1234, name: "MyRoom" });
print("Hashlink: " + link);

var decoded = Hashlink.decode(link);
if (decoded) {
    print("Room: " + decoded.name + " at " + decoded.ip + ":" + decoded.port);
}

Spelling

Spell-checking utilities backed by the server’s spell engine. Backed by JSSpelling.cs.

Methods

Spelling.check(text)

Check whether all words in a text are correctly spelled.
text
string
The text to check.
Returns: string | null — the first misspelled word found, or null if all words are correct (or if the spell engine is not available).

Spelling.confirm(word)

Check whether a single word is correctly spelled.
word
string
A single word to check.
Returns: booleantrue if the word is correctly spelled.

Spelling.suggest(word)

Get spelling suggestions for a word.
word
string
The misspelled word.
Returns: JSSpellingSuggestionCollection — an iterable collection of suggested replacement strings.
function onTextBefore(user, text) {
    var wrong = Spelling.check(stripColors(text));
    if (wrong) {
        var suggestions = Spelling.suggest(wrong);
        var list = [];
        suggestions.forEach(function(s) { list.push(s); });
        print(user, "Did you mean: " + list.slice(0, 3).join(", ") + "?");
    }
    return text;
}

Timer (constructor)

For precise delayed or repeating callbacks, you can instantiate Timer objects. Backed by JSTimerInstance.cs.
var t = new Timer();
t.interval = 5000;        // milliseconds; minimum 500
t.oncomplete = function() {
    print("5 seconds have passed!");
};
t.start();

Properties

PropertyTypeDescription
t.intervalnumberMilliseconds until the callback fires. Minimum 500.
t.oncompletefunctionThe function to call when the timer fires.

Methods

MethodReturnsDescription
t.start()booleanSchedule the timer. Returns true if successfully added to the queue.
t.stop()booleanCancel a pending timer. Returns true if it was in the queue.
Timers fire once and then are removed from the queue. To create a repeating timer, call t.start() again inside the oncomplete callback.

JSUser — user object reference

JSUser objects are passed to most event callbacks and returned by the user() global function. The full list of properties and methods on a user object:

Properties

PropertyTypeAccessDescription
user.namestringread/writeDisplay name. Setting this renames the user server-side.
user.orgNamestringread-onlyOriginal (registered) name.
user.customNamestring | nullread/writeCustom display name override. Set to null to clear.
user.idnumberread-onlySession ID. -1 for linked users.
user.guidstringread-onlyClient GUID string.
user.levelnumberread/writeAdmin level: 0=none, 1=mod, 2=admin, 3=host. Setting requires ScriptCanLevel to be enabled in the server config and cannot promote to owner.
user.ownerbooleanread-onlytrue if this is the room owner.
user.registeredbooleanread-onlytrue if the user’s name is registered.
user.externalIpstringread-onlyExternal IP address.
user.localIpstringread-onlyLocal (LAN) IP address.
user.localEPstringread-onlyLocal endpoint as "ip:port".
user.dnsstringread-onlyReverse DNS hostname.
user.portnumberread-onlyData port.
user.countrystringread-onlyCountry name derived from the country code.
user.regionstringread-onlyRegion string.
user.agenumberread-onlyUser’s reported age.
user.genderstringread-only"Male", "Female", or "Unknown".
user.versionstringread-onlyClient version string.
user.vroomnumberread/writeCurrent virtual room (0–65535).
user.idlebooleanread-onlyWhether the user is currently idle.
user.muzzledbooleanread/writeWhether the user is muzzled (cannot send public messages).
user.cloakedbooleanread/writeWhether the user is cloaked (hidden from the user list).
user.visiblebooleanread-onlytrue if the user is visible in the room list.
user.browsablebooleanread-onlyWhether the user’s file list is publicly browsable.
user.fileCountnumberread-onlyNumber of shared files.
user.fastPingbooleanread-onlyWhether the user is in fast-ping mode.
user.captchabooleanread-onlyWhether the user has passed a captcha check.
user.webClientbooleanread-onlytrue if the user connected via the web client.
user.customClientbooleanread-onlytrue if the user is using a custom sb0t client.
user.ghostbooleanread-onlytrue if the user is ghosting.
user.canHTMLbooleanread-onlytrue if the user’s client supports HTML messages.
user.joinTimenumberread-onlyTimestamp when the user joined.
user.linkedbooleanread-onlytrue if the user is from a linked leaf server.
user.leafJSLeaf | nullread-onlyThe leaf server this user belongs to, or null if local.
user.personalMessagestringread/writeThe user’s personal status message.
user.avatarJSAvatarImageread/writeThe user’s current avatar image.
user.fontJSUserFontread/writeFont settings (enabled, nameColor, textColor, family). Assigning a JSUserFont value copies all font properties.
user.ignoresJSIgnoreCollectionread-onlyThe user’s current ignore list.

Methods

MethodDescription
user.ban()Ban this user. Has no effect on the room owner.
user.disconnect()Disconnect this user. Has no effect on the room owner.
user.redirect(hashlink)Redirect the user to another room by hashlink string.
user.nudge([senderName])Send a nudge to the user (custom clients only). Defaults to Room.botName.
user.sendText(text)Send a public chat line directly to this user as the room bot.
user.sendEmote(text)Send an emote line directly to this user.
user.sendHTML(text)Send an HTML-formatted message to this user (if user.canHTML).
user.setTopic([topic])Send the room topic to this user. Pass no argument to send the current Room.topic.
user.setUrl(addr, text)Send the room URL to this user.
user.restoreAvatar()Restore the user’s avatar to their original.
user.getASN()Return the user’s ASN (Autonomous System Number) as a number.
user.scribble(image[, sender])Send a scribble drawing to this user (custom clients only). image is a JSScribbleImage; optional sender string defaults to Room.botName.

Full example script

The following script demonstrates several static objects working together:
// multifeature/multifeature.js
includeAll();

var joinLog = "joins.txt";

function onLoad() {
    print("multifeature loaded. Room: " + Room.name + " v" + Room.version);

    if (!File.exists(joinLog)) {
        File.save(joinLog, "");
    }
}

function onJoin(user) {
    var line = new Date().toISOString() + " JOIN " + user.name +
               " [" + user.externalIp + "]\n";
    File.append(joinLog, line);
    sendPM(user, Room.botName, "Welcome! Users online: " + Stats.userCount);
}

function onCommand(user, cmd, target, args) {
    if (cmd === "hash") {
        var h = Crypto.md5hash(args);
        print(user, "MD5(" + args + ") = " + h.toHex());
        return;
    }

    if (cmd === "b64") {
        print(user, Base64.encode(args));
        return;
    }

    if (cmd === "find") {
        var results = Channels.search(args);
        results.forEach(function(ch) {
            print(user, ch.name + " (" + ch.users + ")");
        });
        return;
    }

    if (cmd === "stats") {
        print(user, "Users: " + Stats.userCount +
                    " | Peak: " + Stats.peakUserCount +
                    " | Msgs: " + Stats.messageCount);
        return;
    }

    if (cmd === "remember" && user.level >= 1) {
        Registry.setValue("note_" + user.name, args);
        print(user, "Remembered: " + args);
        return;
    }

    if (cmd === "recall") {
        var note = Registry.getValue("note_" + user.name);
        print(user, note ? ("Your note: " + note) : "No note stored.");
        return;
    }
}

function onTimer() {
    // Announce user count every 5 minutes
    var k = "lastAnnounce";
    var last = parseInt(Registry.getValue(k) || "0", 10);
    var now = tickCount();
    if (now - last >= 300000) {
        Registry.setValue(k, now);
        print("Currently " + Stats.userCount + " user(s) in " + Room.name + ".");
    }
}

Build docs developers (and LLMs) love