Spraxium logoSpraxium

Presence Overview

The PresenceManager controls the bot status indicator and activity text across all shards. Learn how to set activities, configure placeholders, and manage the online status.

What the presence system solves

Discord bots display a status indicator (online, idle, do not disturb, invisible) and an activity line below their name (Playing, Watching, Listening, Streaming, Competing). These presence fields are the first thing users see when they check the bot in the member list. The PresenceManager provides a static API for setting and updating these fields from anywhere in your application, including support for per-shard overrides and dynamic placeholder interpolation.

Without a presence manager, you would call client.user.setPresence() directly, which means you need a reference to the client instance, you must guard against calling it before the client is ready, and you have no built-in support for rotating activities or shard-specific text. The PresenceManager handles all of these concerns through a centralized static class that the framework initializes automatically when the bot connects.

The presence system integrates with the sharding system. When your bot runs across multiple shards, each shard can display its own activity text with shard-specific information like the shard number or the guild count on that shard. Built-in placeholders like {{totalServers}} and {{shardNumber}} are resolved automatically from the live client state on every presence update.

Setting a static activity

The simplest use case is setting a fixed activity that stays until you change it. Call PresenceManager.setActivity with a name and a type. The name is the text that appears in the member list, and the type determines the prefix Discord adds (Playing, Watching, Listening, Streaming, or Competing).

src/listeners/ready.listener.ts
import { Events, Listener, Once } from '@spraxium/common';
import { PresenceManager } from '@spraxium/core';

@Listener(Events.ClientReady)
export class ReadyListener {
  @Once()
  onReady(): void {
    PresenceManager.setActivity({
      name: 'your commands',
      type: 'Listening',
    });
  }
}

The setActivity method only changes the activity. It does not touch the status indicator. If you want to change both at once, use setPresence which accepts a status and an activities array. The first activity in the array becomes the current one.

src/listeners/ready.listener.ts
PresenceManager.setPresence({
  status: 'dnd',
  activities: [{ name: 'maintenance mode', type: 'Playing' }],
});

Changing only the status

The setStatus method updates the colored indicator without touching the activity text. Four values are available: 'online' (green), 'idle' (yellow), 'dnd' (red), and 'invisible' (gray, appears offline). This is useful for signaling maintenance windows or degraded states without changing what the activity says.

src/services/health.service.ts
import { PresenceManager } from '@spraxium/core';

PresenceManager.setStatus('idle');

Placeholder interpolation

Activity names support {{key}} placeholders that are resolved from the live client state every time the presence updates. Five built-in variables are available without any extra configuration. They refresh automatically, so a counter like {{totalServers}} stays accurate as guilds are added or removed.

PlaceholderValue
{{shardId}}Current shard ID (0-based)
{{shardNumber}}Current shard number (1-based, shardId + 1)
{{totalShards}}Total number of shards
{{totalServers}}Number of guilds on this shard
{{ping}}WebSocket heartbeat latency in milliseconds

Placeholders work everywhere activities are used: in setActivity, setPresence, startRotation, boot configuration, and shard overrides. If a placeholder key does not resolve, it stays as-is in the output (e.g. {{unknownKey}}), which makes typos easy to spot.

src/listeners/ready.listener.ts
PresenceManager.setActivity({
  name: '{{totalServers}} servers · {{ping}}ms',
  type: 'Watching',
});

Boot configuration

Instead of calling PresenceManager methods in a listener, you can declare the initial presence as a typed constant in the config/ folder and pass it to initPresence on the application builder in main.ts. The framework applies it automatically after the client connects, before any listener fires.

import type { PresenceOptions } from '@spraxium/core';

export const presenceConfig: PresenceOptions = {
  status: 'online',
  activities: [{ name: '{{totalServers}} servers', type: 'Watching' }],
};

initPresence accepts a PresenceOptions object: a status, an activities array, a rotateInterval for automatic cycling, and a perShard record for shard-specific overrides at boot time.

Resetting to boot state

The reset method restores the exact presence that was configured at boot time. It stops any active rotation, resets the status and activity, and restarts rotation if the boot configuration specified one. Per-shard runtime overrides are not cleared by reset, so call clearShardPresence for each shard first if you want a full reset.

src/commands/reset-presence.command.ts
PresenceManager.reset();