Make, copy, import, export, edit and delete the chat profiles your bots talk from, on the Chat Profiles page. Write ads with random choices, item links and variables, set when each runs and what ends it, write the answers to private messages, what a bot does on the channels' lines, the commands it obeys and its status, and read the profile format.
A chat profile says what a bot says on its own: ads it posts in the channels you pick, at random intervals, while their conditions hold; answers to the private messages it gets; what it does on the channels' lines; the commands it obeys; its status. A bot uses several profiles at once, picked on its Chat tab (The chat module), and one profile can serve as many bots as you like.
| Profile | What it is | Can you change it? |
|---|---|---|
| Yours, Yours | Profiles you made, copied or imported. Each is a file in Asterobot's data folder. | Yes. |
| A package's, Package | Shipped by a package you installed, named after it, such as @some-author:traders/wheat. |
No. Copy it to change it. |
The Chat Profiles page
Open Chat Profiles in Asteroboard's menu. The page lists yours by name, then those of your packages.
| Column | What it shows |
|---|---|
| Name | The profile's name, the one a bot's Profiles list shows. |
| Ads | How many ads it holds. |
| Source | Yours or Package, with the package's version. |
| Status | Ready, Can't be used when it has an error, or how many warnings it has. Hover over it to read them. |
The filter above the table finds a profile by name. Each row has a menu:
| Item | What it does |
|---|---|
| Edit | Opens your profile in the editor. View for a package's, which opens read-only. |
| Copy | Saves a copy under a name of your own, then opens it in the editor. |
| Export | Downloads the profile as a .json file. |
| Delete | Deletes one of your profiles, after asking. A package's can't be deleted. |
The page stays current on its own when a profile is saved, imported or deleted, and when a package is installed or removed.
Make a profile
- Click New profile.
- Type a Name, then click Create.
The editor opens on the new, empty profile.
A name is also the profile's file name: it can't be empty, start with @, or contain a / or a character a file name can't hold. The dialog then shows chatprofiles: a profile's name can't be empty, start with @, or hold / or a character a file name can't. A name another profile has gives chatprofiles: a profile already has this name.
Copy, share and delete
Copy, in a row's menu or in the editor, opens a dialog with the name filled in as the original's followed by copy. The copy is yours: that's how you change a package's profile.
Export downloads the profile exactly as it's stored. To use a profile someone shared, click Import, pick the file under Profile file or paste the JSON under Profile JSON, then click Import. The profile joins yours under the name it carries; when you already have one with that name, the dialog asks before Replace it overwrites yours. A profile names items, maps and areas by their game ids, which are the same for everyone playing the same game version.
Delete asks first: "... will be deleted for good. Bots using it drop it from their profiles."
The editor
The editor shows the profile's form on the left and its JSON on the right, both live: a field changed in the form shows in the JSON at once, and JSON you type fills the form once it reads. Save sends the profile to Asterobot, which checks it, and every bot using it follows at once. A profile Asterobot can't accept is refused with the field at fault, such as chat: malformed profile: ads[0].messages: an ad needs a message. Its warnings show above the form, under Worth knowing.
A package's profile opens read-only, with Copy to make one yours. Leaving the editor with unsaved changes asks first.
General
Name and Description. Renaming a profile moves every bot using it to the new name.
Variables
Values the messages read by name: a message writing {price} says the value of price. Add a variable, then type its Name and its Value. When several profiles of a bot set the same variable, the first profile's value wins; a script can set its own, which win over every profile's. The character's own, such as {name} or {level}, can't be replaced.
Ads
Add an ad adds one, in Trade, waiting two to four minutes between sends, with one message to write.
| Field | What it does |
|---|---|
| Name | Optional: the name the bot's Chat tab shows. Without one, it shows Ad 1, Ad 2... |
| Channels | Where each send goes, named and coloured as in the game. Each send goes to every channel: a channel still in its cooldown is waited for, the others go. |
| Messages | One is said each time. Each shows a preview below it. See Messages. |
| Order | At random, never the same message twice in a row, or In order. |
| Wait at least, Wait at most | The random wait between two sends, from 1 second to 24 hours, in seconds, minutes or hours. |
| Only when | The ad's condition: it waits while the condition doesn't hold. See Conditions. |
| Stop | What ends the ad for good. See Stop. |
| With each send | An Emoticon or an Emote the character plays as it says the message. |
Messages
A message is a template that the bot fills in each time it says it:
| You write | The bot says |
|---|---|
{Hi|Hello|Hey} |
One of the choices, at random. Choices can be nested and empty: {!|}. |
{item:289} |
A link to the item, as the game's own item links, from the character's inventory. One in the bags is preferred to a worn one. |
{name}, {level}, {server}, {subarea}, {area}, {position}, {kamas}, {pods}, {time} |
The character's name, level, server, subarea, area, position as a link to its map, which the game shows as [4,-19], kamas, pods as used/max, and the time as HH:MM. |
{sender} |
In a reply, a trigger's message or the status reply: who wrote the message or the line. |
{price}, or any other name |
A variable. |
A message isn't sent while one of its variables has no value or the character doesn't have an item it links: the ad waits, and the Chat tab says why. Neither is a message past the game's 256 characters or 16 item links.
The preview under each message shows a few fills, each item link as [its name], in the colour of the ad's first channel, and the longest the message can be against the game's limits: "Up to 74/256 characters, 1/16 item links". It's made without a bot, so the character's variables stay written as {name}, and items are named in the game language you read the game in.
Conditions
Only when holds tests, all of which must hold, and groups: All of these, Any of these, and Not this one. Without a test, the ad always runs.
| Test | Holds when |
|---|---|
| Time | The computer's time is between From and To, past midnight when To comes first, on one of the Days ticked, every day when none is. |
| In a fight, On a trip | The character is in a fight, or on a trip, or isn't: Yes or No. |
| Map, Subarea, Area | The character is on one of these. |
| Has an item | The character has at least this many of the item. |
| Kamas, Level | The character's kamas or level is Above and Below the numbers given. |
| A flag | A script, or an alarm's Set a flag reaction, has set this flag. |
A test about something the bot doesn't know yet, such as its kamas before the game has sent the inventory, doesn't hold.
Stop
The Stop ends the ad for good, whichever comes first: After so many sends, a time After its first send, or On a date, on the computer's clock. The counts are kept in memory: they start over when Asterobot restarts or the bot's profiles change.
Replies
The answers to the private messages a bot gets (Replies). Add a rule adds one, answering any message with one reply to write.
| Field | What it does |
|---|---|
| Answers when | The rule's condition: the tests an ad takes, and two more about the message. Without a test, the rule answers any message. |
| Replies | One is picked at random. They're messages, and {sender} says who wrote. The preview shows {sender} as Player. |
| Answers per player | At most this many answers from the rules to one player, In this time. One an hour by default, which answers the first message of a conversation. |
The first rule whose test holds answers, so a rule without a test goes last: the arrows move a rule up or down. When a bot has several profiles, their rules add up in profile order, and the first profile with Answers per player sets it.
A reply rule's condition can also test the message:
| Test | Holds when |
|---|---|
| Sender | The character who wrote is one of the Names, capitals ignored. |
| Words | The message has one of the Keywords as a word, Contains a text, and matches the Regex: each one you fill in must hold. Keywords and Contains ignore capitals and accents, so ble finds blé. The regex is as written, in Go's syntax: (?i) at its start ignores capitals. |
Triggers
What a bot does on a line said in a channel (Triggers). Add a trigger adds one, on a line in Trade that none of your bots said, with a whisper to write.
| Field | What it does |
|---|---|
| Name | What the trigger is called in the Chat tab and the console, and in the alarm event and the script event it gives. |
| Fires when | The trigger's condition: an ad's tests, a reply's Sender and Words, and four more about the line, below. Without a test, it fires on any line of any channel. |
| Actions | What it does, in order, each once the one before is done. The arrows move an action up or down. |
| Per player | One player fires it at most this many times, In this time. Once an hour by default. |
Every trigger whose test holds fires, so one line can fire several. When a bot has several profiles, their triggers add up.
A trigger's condition can also test the line:
| Test | Holds when |
|---|---|
| Channel | The line was said in one of these channels. |
| One of your bots | Yes: one of your other accounts in this Asterobot said it. No: anybody else did. |
| Names the character | The line has the name of the bot's character as a word, capitals and accents ignored. |
| Links an item | The line links this item. |
| Action | What it does |
|---|---|
| Whisper the sender | Whispers one of its messages, picked at random. {sender} says who wrote the line. |
| Say in a channel | Says a message in the channel you pick. |
| Raise an alarm event | Raises the event trigger:<name> for the alarms: a rule naming it decides what follows, such as a notification. |
| Tell the script | The bot's script hears it (onChat). |
| Ignore the sender | Adds the sender to the character's ignore list, as the game's menu does: their lines are hidden for the rest of the game session, and fire nothing more. If the game refuses, such as when the list is full, the console says why. |
| Play a smiley, Play an emote | Plays the one you pick. |
| Invite to the party | Invites the sender to the character's party. |
| Pause the chat | The bot sends nothing for this long, as with Stop sending. |
A whisper or a message waits the timing, as a reply does. In a dry run, the messages, the ignore, the invitation and the smiley or emote are only written to the console.
Commands
The commands a bot obeys (Commands). Turn on Obeys commands to set them; without it, the profile takes no command. The bot's first profile that takes commands sets them all.
| Field | What it does |
|---|---|
| Prefix | What a command starts with, up to 3 characters. ! by default. |
| Trusted names | Characters on the bot's own server whose commands it obeys. Type a name and press Enter. |
| Your bots | Your other accounts in this Asterobot are trusted too, whatever their character. On by default. |
| Commands that work | The commands the bot obeys. All of them by default. |
| Status reply | What !status answers, a message. Empty, it's {name}, level {level}, {subarea} {position}, {kamas} kamas, {pods} pods. |
Status
The status the character takes while the bot's Status part is on (Status). Turn on Sets the status and pick Available, Away, Private or Solo, as the game's status menu has them. Away takes an Away message, up to 256 characters, which players read when they write to the character in private. The bot's first profile with a status sets it.
Private keeps strangers' private messages out, so the replies get none: the editor warns you.
Timing
How long the bot takes to answer, as a person would: a random time to read the message, between Reads at least and Reads at most seconds (2 to 6 by default, 120 at most), then the time to type the answer at Characters a second (6 by default, 50 at most). The bot's first profile with a timing sets it, for the replies, the triggers' messages and the answer to !status.
The format
A profile is a JSON file. This is the format the editor writes, and the one Export and Import use:
{
"version": 1,
"name": "Sell wheat in Astrub",
"description": "Wheat ads in Trade, in the evening, and price answers.",
"variables": { "price": "12" },
"ads": [
{
"name": "Wheat ad",
"channels": ["SALES"],
"messages": ["{Selling|WTS} {item:289} at {price} k each, /w me", "{item:289} for sale, {price} k, /w {name}"],
"order": "random",
"every": { "min": 120, "max": 240 },
"when": { "all": [ { "time": { "from": "18:00", "to": "23:30" } }, { "map.subarea": { "in": [95] } }, { "bot.inFight": false } ] },
"stop": { "after": 50, "for": 7200, "until": "2026-11-01T20:00" },
"smiley": 1
}
],
"replies": {
"rules": [
{ "when": { "text": { "keywords": ["price", "prix", "combien"] } }, "reply": ["{price} k each, {come|meet me} in Astrub"] },
{ "reply": ["{Hi|Hello} {sender}, busy for now, I'll answer later"] }
],
"perPlayer": { "max": 1, "every": 3600 }
},
"triggers": [
{
"name": "wtb",
"when": { "channel": { "in": ["SALES"] }, "text": { "keywords": ["wtb", "buy"] }, "items": { "has": 289 } },
"do": [ { "whisper": ["Hi {sender}, I sell {item:289} at {price} k"] }, { "raise": "wtb" } ],
"perPlayer": { "max": 1, "every": 21600 }
}
],
"commands": {
"prefix": "!",
"trusted": { "names": ["Master-Name"], "myBots": true },
"builtIn": ["stop", "start", "pause", "resume", "say", "status", "disconnect"],
"statusReply": "lvl {level}, {subarea} {position}, {kamas} k, {pods}"
},
"status": { "set": "away", "text": "farming, back later" },
"timing": { "read": { "min": 2, "max": 6 }, "typing": 6 }
}
| Field | Values | Default |
|---|---|---|
version |
1 |
required |
name |
text | required |
description |
text | none |
variables |
name → text; a name can't hold braces, | or : |
none |
ads[].name |
text | none |
ads[].channels |
channels as the game's protocol names them: SALES is Trade, SEEK Recruitment, GLOBAL General, COMMUNITY Community, GUILD, ALLIANCE, PARTY, TEAM, ARENA |
required |
ads[].messages |
templates | at least one |
ads[].order |
random, inOrder |
random |
ads[].every |
min, max: seconds, 1 to 86400 |
required |
ads[].when |
tests, and all, any, not: time (from, to, days as mon...sun), bot.inFight and bot.onTrip (true, false), map.id, map.subarea, map.area (is an id, in a list), inventory.has (item, atLeast), kamas and level (above, below), flag (a name) |
always |
ads[].stop |
after (sends), for (seconds from the first send), until (a date such as 2026-11-01T20:00, on the computer's clock) |
none |
ads[].smiley, ads[].emote |
an emoticon's or an emote's id, not both | none |
replies.rules[].when |
an ad's tests, and sender.name (is a name, in a list) and text (contains, keywords, regex) |
always |
replies.rules[].reply |
templates, which read {sender} |
at least one |
replies.perPlayer |
max answers, every seconds (1 to 86400) |
1 every 3600 |
triggers[].name |
text | required |
triggers[].when |
a reply's tests, and channel (is a channel, in a list), sender.myBot and text.mentionsMe (true, false), items (has an item's id) |
always |
triggers[].do |
actions, each an object of one key: whisper (templates, which read {sender}), say (channel, text), raise (the event's name), script, ignore and invite (true), smiley and emote (an id), pauseChat (seconds, 1 to 86400) |
at least one |
triggers[].perPlayer |
max times, every seconds (1 to 86400) |
1 every 3600 |
commands.prefix |
up to 3 characters, no space | ! |
commands.trusted |
names (characters on the bot's server), myBots (true, false) |
no names, myBots true |
commands.builtIn |
stop, start, pause, resume, say, status, disconnect |
all of them |
commands.statusReply |
a template | {name}, level {level}, {subarea} {position}, {kamas} kamas, {pods} pods |
status |
set: available, away, private, solo; text, with away only, up to 256 characters |
not changed |
timing.read |
min, max: seconds, 0 to 120 |
2 to 6 |
timing.typing |
characters a second, 1 to 50 | 6 |
A field this version doesn't read is kept as it is and ignored, so a profile written for a later version still loads.
Errors and warnings
An error keeps the profile from being used, and its message names the field: a wrong type, a channel the game doesn't know, an empty message, unbalanced braces in a template, a wait out of range, a test it doesn't know, a test about the message in an ad's condition or about a channel's line in a reply's, a regex that doesn't compile, a command, an action or a status that isn't one. A profile with an error is listed with Can't be used, and bots skip it.
A warning is only worth knowing:
ads[0].messages[1]: {buyer} is set by no variable here: a script or another profile must set itads[0].messages[0]: {sender} never has a value in an ad: the message isn't sentstatus.set: private keeps strangers' whispers out: the replies get noneitem 289: not in the game data, for an id the newest game version you installed doesn't have.name: "Wheat", but its file is "wheat.json": bots use it as "wheat", for a file you renamed by hand.
Profile files
Your profiles are files in the chatprofiles folder of Asterobot's data folder, one <name>.json each, in exactly the format above (Files and folders). A bot reads its profiles again when it connects and when its chat settings change, so a file you edit by hand plays from then on.
A package ships its profiles as chatprofiles/<name>.json at its root. They're listed as @publisher:package/<name>, and every bot uses the newest version of the package you installed.