Skip to content

Presence Module

The Presence API allows you to control how the bot appears to other users on WhatsApp. You can toggle its global online status, or trigger “typing…” and “recording audio…” indicators in specific chats.

These indicators are fantastic for improving user experience (UX). When a command takes several seconds to execute (like querying a database or fetching an API), triggering a typing indicator lets the user know the bot is actively processing their request.

The Presence API is accessible from three different locations depending on your context:

  1. Inside a Command (ChatContext): Use ctx.Presence for quick, scoped actions within the current chat context (such as ctx.Presence.StartTyping()).
  2. On the Bot Instance directly: Use bot.Presence for global presence operations (such as bot.Presence.SetGlobalPresenceState("online")).
  3. Via api.InternalSocket: Use api.InternalSocket.Presence (which points to the exact same object as bot.Presence) inside or outside command callbacks.

You can configure the bot’s global visibility. By default, the bot usually appears online when connected. You can explicitly set it to offline if you want the bot to operate in “stealth” mode.

// Usually done on bot startup
await bot.InternalSocket.Presence.SetGlobalPresenceState("offline");
// OR
await bot.InternalSocket.Presence.SetGlobalPresenceState("online");

These methods trigger the indicators that appear at the top of a chat (e.g., “typing…” or “recording audio…”).

Use these methods to manually toggle the text typing indicator.

public async run(ctx: IChatContext, api: AdditionalAPI, args: CommandArgs): Promise<void> {
// 1. Turn on the typing indicator
await ctx.Presence.StartTyping();
// 2. Perform a slow task
const data = await mySlowDatabaseQuery();
// 3. Turn off the typing indicator
await ctx.Presence.StopTyping();
// 4. Send the result
await ctx.SendText(`Here are the results: ${data}`);
}

Use these methods if your command generates and sends Voice Notes (audio files). It shows “recording audio…” instead of “typing…”.

public async run(ctx: IChatContext, api: AdditionalAPI, args: CommandArgs): Promise<void> {
await ctx.Presence.StartRecording();
const audioBuffer = await generateTextToSpeech("Hello!");
await ctx.Presence.StopRecording();
await ctx.SendAudio(audioBuffer);
}

Manually calling Start and Stop can be risky. If an error is thrown during your slow task (e.g., your database query fails), the StopTyping line might never execute, leaving the bot stuck “typing…” forever in that chat.

To solve this cleanly, WhatsBotCord provides Wrapper Methods: WithTyping and WithRecording.

These methods accept an asynchronous callback function. They will automatically turn the indicator ON, execute your function, and guarantee the indicator is turned OFF when the function completes (even if it throws an error!).

public async run(ctx: IChatContext, api: AdditionalAPI, args: CommandArgs): Promise<void> {
// The indicator will stay active for as long as this inner callback runs
await ctx.Presence.WithTyping(async () => {
const apiResponse = await fetch("https://api.example.com/data");
const data = await apiResponse.json();
await ctx.SendText(`Data fetched: ${data.result}`);
});
// <-- Stops typing automatically right here!
}

Works identically, but displays the “recording audio…” indicator instead.

public async run(ctx: IChatContext, api: AdditionalAPI, args: CommandArgs): Promise<void> {
await ctx.Presence.WithRecording(async () => {
const audioBuffer = await generateTextToSpeech("Hello!");
await ctx.SendAudio(audioBuffer);
});
}