Skip to content

Users & presence

A user is an account that has joined a server. Presence is whether that user is connected right now, plus their status and the apps and devices they’re using. This page explains how the server tracks both and who gets to see what.

{
"username": "mist",
"nickname": "Mist",
"roles": ["admin", "user"],
"color": "#FF0000",
"cracked": false,
"status": { "status": "online", "text": "Shipping docs" },
"clients": ["originchats"],
"devices": ["computer"]
}

Commands and events identify users by username. Two flags classify an account:

  • cracked: true marks a local account created on this server rather than a Rotur account. See server accounts.
  • bot: true marks an account that declared itself a bot. The field is left out for other accounts.

Neither flag grants or removes any permission. See the user schema for every field, and users_list and users_online to load them.

One user can have several WebSocket connections open at once, for example a desktop app and a phone. The server groups them by account.

Event When it’s sent
user_join An account joins the server for the first time, or rejoins after leaving.
user_connect The user’s first connection opens.
user_disconnect The user’s last connection closes.
user_leave The user leaves the server or is banned.

Opening a second connection doesn’t send another user_connect, and closing one of several doesn’t send user_disconnect.

Authenticating again on the same connection updates it in place, so the user isn’t counted twice. Authenticating as a different account moves the connection from the old account to the new one.

A user sets their status with status_set:

Status Meaning
online Available.
idle Away.
dnd Do not disturb.
invisible Connected, but shown as offline to most people.
offline Shown as offline, like invisible.

Status can include up to 100 characters of text. A user with no open connections always appears offline.

invisible and offline hide a connected user. Who can see through that depends on the viewer:

  • The user themselves and anyone with manage_users see the real status and the user’s clients and devices.
  • Everyone else sees offline with empty status text, and empty clients and devices lists.
  • Public HTTP user pages have no viewer, so they always show empty clients and devices.

When a user’s status changes, each viewer gets the events that match what they can see:

Change Ordinary viewers get The user and manage_users viewers get
Goes invisible or offline user_disconnect with the hidden user status_get, then user_clients
Comes back to a visible status user_connect, then status_get status_get, then user_clients
Changes between visible statuses status_get status_get, then user_clients

While a user stays hidden, ordinary viewers get no events about their connections opening or closing.

Access to hidden presence follows the manage_users permission, which roles grant. After a command that can change roles or permissions, the server re-checks every connected viewer. Those commands are role create, update, and delete, user_roles_set, self_role_add and self_role_remove, bans and unbans, config_update, and slash commands. A viewer who gains manage_users receives user_connect for each connected user who is hidden. A viewer who loses it receives user_disconnect for each of them.

Each connection can report the app name and device type it’s running on when it authenticates. See authentication metadata for the accepted values. The server combines these into two lists per user:

{
"cmd": "user_clients",
"username": "mist",
"clients": ["mychat", "mychat-cli"],
"devices": ["computer", "mobile"]
}
  • clients holds app names. Connections only add one if they sent it when authenticating.
  • devices holds device types. If a connection doesn’t send one, the server tries to work it out from the connection’s User-Agent header.

Each list is sorted and has no duplicates. The lists aren’t paired, so you can’t tell which app runs on which device. The handshake capability user_metadata_v1 means the server supports these fields and this event.

The server sends user_clients when a connected user’s lists change without their first connection opening or last one closing:

  • A new connection adds an app or device that wasn’t listed yet.
  • A closing connection removes the last one using an app or device.

The event goes to each viewer who can see the change, including the user’s own other connections. A second connection that adds nothing new sends no event. The first connection and the last disconnection are covered by user_connect and user_disconnect, which carry the lists in their user object.

Handle user_clients like this:

  • Replace only that user’s clients and devices.
  • Don’t change their status, roles, nickname, bot flag, or membership.
  • Ignore it if the user has already left. Don’t recreate them.

user_clients is server-sent only. Clients can’t request it, and it has no permission of its own.

These lists are self-reported and only last while the connections are open. The server doesn’t verify them, and they aren’t saved with messages. See the client lifecycle for when to expect each event.