Skip to content

Setting Custom Activity and Presence

Customizing Your Bot’s Presence and Activity

Custom statuses and activities are a great way to make your bot more engaging and informative for users. With Seyfert, you can define your bot’s activity and presence during client initialization or dynamically update them after the bot is running. This guide explores both approaches and provides recommendations for achieving the best results.

Setting Presence During Client Initialization

The most straightforward way to define your bot’s status and activity is during client initialization. Below is an example of setting the bot’s presence:

src/index.ts
import {
class Client<Ready extends boolean = boolean>
Client
} from "seyfert";
const
const client: Client<boolean>
client
= new
new Client<boolean>(options?: ClientOptions): Client<boolean>
Client
({
ClientOptions.presence?: (shardId: number) => GatewayPresenceUpdateData
presence
: (
shardId: number
shardId
) => ({
GatewayPresenceUpdateData.status: PresenceUpdateStatus
status
: PresenceUpdateStatus.
function (enum member) PresenceUpdateStatus.Idle = "idle"
Idle
,
GatewayPresenceUpdateData.activities: GatewayActivityUpdateData[]
activities
: [{
name: string

The activity's name

name
: "your servers",
type: ActivityType.
function (enum member) ActivityType.Watching = 3

Watching {details}

Watching
,
}],
GatewayPresenceUpdateData.since: number | null

Unix time (in milliseconds) of when the client went idle, or null if the client is not idle

since
:
var Date: DateConstructor

Enables basic storage and retrieval of dates and times.

Date
.
DateConstructor.now(): number

Returns the number of milliseconds elapsed since midnight, January 1, 1970 Universal Coordinated Time (UTC).

now
(),
GatewayPresenceUpdateData.afk: boolean

Whether or not the client is afk

afk
: false,
})
});

Explanation:

  • status: Defines the bot’s online status. Possible values are online, idle, dnd (Do Not Disturb), or invisible.
  • activities: An array of activities the bot is engaged in. Each activity requires:
    • name: The custom status message.
    • type: The activity type, such as Playing, Listening, Watching, etc. These types are constants in the ActivityType enum.

Rendering the Bot as “Mobile”

To display your bot as if it’s running on a mobile device, you can specify custom gateway properties. Here’s how:

const
const client: Client<boolean>
client
= new
new Client<boolean>(options?: ClientOptions): Client<boolean>
Client
({
ClientOptions.gateway?: {
properties?: Partial<ShardManagerOptions["properties"]>;
compress?: ShardManagerOptions["compress"];
}
gateway
: {
properties?: Partial<IdentifyProperties | undefined>
properties
: {
os?: string

Operating system the shard runs on.

@default"darwin" | "linux" | "windows"

os
: 'android',
browser?: string

The "browser" where this shard is running on.

browser
: 'Discord Android',
device?: string

The device on which the shard is running.

device
: 'android'
}
},
ClientOptions.presence?: (shardId: number) => GatewayPresenceUpdateData
presence
: (
shardId: number
shardId
) => ({
GatewayPresenceUpdateData.status: PresenceUpdateStatus
status
: PresenceUpdateStatus.
function (enum member) PresenceUpdateStatus.Idle = "idle"
Idle
,
GatewayPresenceUpdateData.activities: GatewayActivityUpdateData[]
activities
: [{
name: string

The activity's name

name
: "your servers",
type: ActivityType.
function (enum member) ActivityType.Watching = 3

Watching {details}

Watching
,
}],
GatewayPresenceUpdateData.since: number | null

Unix time (in milliseconds) of when the client went idle, or null if the client is not idle

since
:
var Date: DateConstructor

Enables basic storage and retrieval of dates and times.

Date
.
DateConstructor.now(): number

Returns the number of milliseconds elapsed since midnight, January 1, 1970 Universal Coordinated Time (UTC).

now
(),
GatewayPresenceUpdateData.afk: boolean

Whether or not the client is afk

afk
: false,
})
});

Important Notes:

  • gateway.properties: Defines the operating system, browser, and device to emulate. When set to mimic a mobile device (e.g., os: 'android'), the bot will appear with a mobile icon.
  • Avoiding status: If you set the status property explicitly, the mobile icon will not be rendered. For example, leaving status undefined allows the mobile icon to appear.

Dynamically Updating Presence

Once the bot is running, you can dynamically update its presence by creating a command to handle presence updates. This is particularly useful when the update is triggered by user interaction or other events:

src/commands/presence.ts
import {
class Command
Command
,
function Declare(declare: CommandDeclareOptions): <T extends {
new (...args: any[]): object;
}>(target: T) => {
new (...args: any[]): {
name: string;
nsfw: boolean | undefined;
props: ExtraProps | undefined;
contexts: InteractionContextType[];
integrationTypes: ApplicationIntegrationType[];
defaultMemberPermissions: bigint | undefined;
botPermissions: bigint | undefined;
description: string;
type: ApplicationCommandType;
guildId?: string[];
ignore?: IgnoreCommand;
aliases?: string[];
handler?: EntryPointCommandHandlerType;
};
} & T
Declare
,
interface GuildCommandContext<T extends OptionsRecord = {}, M extends keyof RegisteredMiddlewares = never>
GuildCommandContext
} from "seyfert";
@
function Declare(declare: CommandDeclareOptions): <T extends {
new (...args: any[]): object;
}>(target: T) => {
new (...args: any[]): {
name: string;
nsfw: boolean | undefined;
props: ExtraProps | undefined;
contexts: InteractionContextType[];
integrationTypes: ApplicationIntegrationType[];
defaultMemberPermissions: bigint | undefined;
botPermissions: bigint | undefined;
description: string;
type: ApplicationCommandType;
guildId?: string[];
ignore?: IgnoreCommand;
aliases?: string[];
handler?: EntryPointCommandHandlerType;
};
} & T
Declare
({
name: string
name
: 'presence',
description: string
description
: 'Change bot presence'
})
export default class
class PresenceCommand
PresenceCommand
extends
class Command
Command
{
async
PresenceCommand.run(ctx: GuildCommandContext): Promise<void>
run
(
ctx: GuildCommandContext<{}, never>
ctx
:
interface GuildCommandContext<T extends OptionsRecord = {}, M extends keyof RegisteredMiddlewares = never>
GuildCommandContext
) {
ctx: GuildCommandContext<{}, never>
ctx
.
client: UsingClient
client
.
Client<true>.gateway: ShardManager
gateway
.
ShardManager.setPresence(payload: GatewayUpdatePresence["d"]): void
setPresence
({
GatewayPresenceUpdateData.activities: GatewayActivityUpdateData[]
activities
: [{
name: string

The activity's name

name
: "with Seyfert",
type: ActivityType.
function (enum member) ActivityType.Playing = 0

Playing {game}

Playing
,
}],
GatewayPresenceUpdateData.status: PresenceUpdateStatus
status
: PresenceUpdateStatus.
function (enum member) PresenceUpdateStatus.Online = "online"
Online
,
GatewayPresenceUpdateData.since: number | null

Unix time (in milliseconds) of when the client went idle, or null if the client is not idle

since
:
var Date: DateConstructor

Enables basic storage and retrieval of dates and times.

Date
.
DateConstructor.now(): number

Returns the number of milliseconds elapsed since midnight, January 1, 1970 Universal Coordinated Time (UTC).

now
(),
GatewayPresenceUpdateData.afk: boolean

Whether or not the client is afk

afk
: false
});
await
ctx: GuildCommandContext<{}, never>
ctx
.
editOrReply<false>(body: InteractionCreateBodyRequest | InteractionMessageUpdateBodyRequest, withResponse?: false | undefined): Promise<...>
editOrReply
({
content: string
content
: 'Switched Presence' });
}
}

Explanation:

  • Command Definition: The @Declare decorator defines a command called presence to handle presence updates.
  • setPresence Method: Updates the bot’s activities, status, and additional details dynamically.
  • User Feedback: After updating the presence, the bot confirms the action by sending a message.

Best Practices

  1. Use Meaningful Activities: Ensure that your activity messages are clear and provide value to your users. For example, a bot managing a server could display “Watching over your server” or “Playing with configuration settings.”
  2. Dynamic Updates for Engagement: Consider updating the bot’s activity periodically to reflect its current state or to keep users engaged.
  3. Test Mobile Presence Carefully: When emulating a mobile presence, always test to ensure that the intended icon displays correctly. Avoid setting the status property if you want the mobile icon to appear.
  4. Respect Discord’s Terms of Service: Ensure that your custom statuses and activities align with Discord’s guidelines to avoid any potential issues.

By leveraging these techniques, you can create a bot presence that not only stands out but also enhances the overall user experience.