Skip to content

Listening to Events

Updating Seyfert’s Configuration

Before starting this section, you need to update the seyfert.config.mjs file to specify the location of the event files for Seyfert.

seyfert.config.mjs
import {
const config: {
bot(data: RuntimeConfig): InternalRuntimeConfig;
http(data: RuntimeConfigHTTP): InternalRuntimeConfigHTTP;
}
config
} from 'seyfert';
export default
const config: {
bot(data: RuntimeConfig): InternalRuntimeConfig;
http(data: RuntimeConfigHTTP): InternalRuntimeConfigHTTP;
}
config
.
function bot(data: RuntimeConfig): InternalRuntimeConfig

Configurations for the bot.

@paramdata - The runtime configuration data for gateway connections.

@returnsThe internal runtime configuration.

bot
({
token: string
token
:
var process: NodeJS.Process
process
.
NodeJS.Process.env: NodeJS.ProcessEnv

The process.env property returns an object containing the user environment. See environ(7).

An example of this object looks like:

{
TERM: 'xterm-256color',
SHELL: '/usr/local/bin/bash',
USER: 'maciej',
PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin',
PWD: '/Users/maciej',
EDITOR: 'vim',
SHLVL: '1',
HOME: '/Users/maciej',
LOGNAME: 'maciej',
_: '/usr/local/bin/node'
}

It is possible to modify this object, but such modifications will not be reflected outside the Node.js process, or (unless explicitly requested) to other Worker threads. In other words, the following example would not work:

Terminal window
node -e 'process.env.foo = "bar"' && echo $foo

While the following will:

import { env } from 'node:process';
env.foo = 'bar';
console.log(env.foo);

Assigning a property on process.env will implicitly convert the value to a string. This behavior is deprecated. Future versions of Node.js may throw an error when the value is not a string, number, or boolean.

import { env } from 'node:process';
env.test = null;
console.log(env.test);
// => 'null'
env.test = undefined;
console.log(env.test);
// => 'undefined'

Use delete to delete a property from process.env.

import { env } from 'node:process';
env.TEST = 1;
delete env.TEST;
console.log(env.TEST);
// => undefined

On Windows operating systems, environment variables are case-insensitive.

import { env } from 'node:process';
env.TEST = 1;
console.log(env.test);
// => 1

Unless explicitly specified when creating a Worker instance, each Worker thread has its own copy of process.env, based on its parent thread's process.env, or whatever was specified as the env option to the Worker constructor. Changes to process.env will not be visible across Worker threads, and only the main thread can make changes that are visible to the operating system or to native add-ons. On Windows, a copy of process.env on a Worker instance operates in a case-sensitive manner unlike the main thread.

@sincev0.1.27

env
.
string | undefined
BOT_TOKEN
?? '',
intents?: number | IntentStrings | number[]
intents
: ['Guilds'],
locations: RCLocations
locations
: {
RCLocations.base: string
base
: 'dist',
RCLocations.commands?: string
commands
: 'commands',
RCLocations.events?: string
events
: 'events' // - src/events will be our folder for events
}
});

Listening to Events

Each event file must export the createEvent function as the default export so Seyfert can load it.
The createEvent function takes an object with two properties: data and run.

Let’s listen to the botReady event as the first example:

src/events/botReady.ts
import {
function createEvent<E extends ClientNameEvents | CustomEventsKeys>(data: {
data: {
name: E;
once?: boolean;
};
run: (...args: ResolveEventParams<E>) => any;
}): {
data: {
name: E;
once?: boolean;
};
run: (...args: ResolveEventParams<E>) => any;
}

Creates an event with the specified data and run function.

@paramdata - The event data.

@returnsThe created event.

@example const myEvent = createEvent({ data: { name: 'ready', once: true }, run: (user, client, shard) => { client.logger.info(Start ${user.username} on shard #${shard}); } });

createEvent
} from 'seyfert';
export default
createEvent<"botReady">(data: {
data: {
name: "botReady";
once?: boolean;
};
run: (args_0: ClientUser, args_1: UsingClient, args_2: number) => any;
}): {
data: {
name: "botReady";
once?: boolean;
};
run: (args_0: ClientUser, args_1: UsingClient, args_2: number) => any;
}

Creates an event with the specified data and run function.

@paramdata - The event data.

@returnsThe created event.

@example const myEvent = createEvent({ data: { name: 'ready', once: true }, run: (user, client, shard) => { client.logger.info(Start ${user.username} on shard #${shard}); } });

createEvent
({
// botReady is triggered when all shards and servers are ready.
// `once` ensures the event runs only once.
data: {
name: "botReady";
once?: boolean;
}
data
: {
once?: boolean
once
: true,
name: "botReady"
name
: 'botReady' },
run: (args_0: ClientUser, args_1: UsingClient, args_2: number) => any
run
(
user: ClientUser
user
,
client: UsingClient
client
) {
Log: We can use client.logger to display messages in the console.
client: UsingClient
client
.
BaseClient.logger: Logger
logger
.
Logger.info(...args: any[]): void

Logs an info message.

@paramargs The arguments to log.

info
(`${
user: ClientUser
user
.
username: string
username
} is ready`);
}
})

As a second example, let’s look at the guildDelete event emitted by Discord when a bot is removed from a server or the server is deleted:

src/events/guildDelete.ts
import {
function createEvent<E extends ClientNameEvents | CustomEventsKeys>(data: {
data: {
name: E;
once?: boolean;
};
run: (...args: ResolveEventParams<E>) => any;
}): {
data: {
name: E;
once?: boolean;
};
run: (...args: ResolveEventParams<E>) => any;
}

Creates an event with the specified data and run function.

@paramdata - The event data.

@returnsThe created event.

@example const myEvent = createEvent({ data: { name: 'ready', once: true }, run: (user, client, shard) => { client.logger.info(Start ${user.username} on shard #${shard}); } });

createEvent
} from 'seyfert';
export default
createEvent<"guildDelete">(data: {
data: {
name: "guildDelete";
once?: boolean;
};
run: (args_0: APIUnavailableGuild | Guild<"cached">, args_1: UsingClient, args_2: number) => any;
}): {
...;
}

Creates an event with the specified data and run function.

@paramdata - The event data.

@returnsThe created event.

@example const myEvent = createEvent({ data: { name: 'ready', once: true }, run: (user, client, shard) => { client.logger.info(Start ${user.username} on shard #${shard}); } });

createEvent
({
data: {
name: "guildDelete";
once?: boolean;
}
data
: {
name: "guildDelete"
name
: 'guildDelete' },
run: (args_0: APIUnavailableGuild | Guild<"cached">, args_1: UsingClient, args_2: number) => any
run
(
unguild: APIUnavailableGuild | Guild<"cached">
unguild
,
client: UsingClient
client
) {
// unguild is the server from which the bot was removed or deleted.
// It is also possible that the server was simply deleted.
if (
unguild: APIUnavailableGuild | Guild<"cached">
unguild
.
unavailable?: boolean | undefined

true if this guild is unavailable due to an outage

unavailable
) return;
client: UsingClient
client
.
BaseClient.logger: Logger
logger
.
Logger.info(...args: any[]): void

Logs an info message.

@paramargs The arguments to log.

info
(`I was removed from: ${
unguild: APIUnavailableGuild | Guild<"cached">
unguild
.
APIUnavailableGuild.id: string

Guild id

id
}`);
}
})

After completing these steps, your project structure should look like this:

  • Directorysrc
    • Directorycommands
      • ping.ts
    • Directoryevents
      • botReady.ts
      • guildDelete.ts
    • index.ts
  • package.json
  • seyfert.config.mjs
  • tsconfig.json
  • .env