Gryt

API reference

Everything @gryt/bot exports, generated from the source

This is the reference. Writing a bot is the page that teaches the shape: the handshake, waiting to be approved, and what a bot does when an admin says no.

Everything below is exported from @gryt/bot. Nothing else in the package is public.

import { GrytBot, parseCommand, splitArgs, createIdentity, loadIdentity, PERMISSIONS_BEFORE_CATALOGUE } from "@gryt/bot";

GrytBot

A bot on one Gryt server.

It joins like any other client and is a member like any other: no bot account type, no bot token, no bypass. What it may do is what its role says.

So the interesting failure is a permission failure. can() answers from what the server said, and sending without the permission throws here with the permission's name rather than surfacing as a server:error later.

const bot = new GrytBot({ host: "localhost:5001", nickname: "Helper" });

bot.command("ping", async (ctx) => ctx.reply("pong"), {
  description: "Check I am alive",
  requires: ["send_messages"],
});

await bot.start();

can()

can(permission: Permission): boolean

False before ready: a bot acting on what it assumes it may do finds out over the wire. True for a permission the server's catalogue does not have — that is a server older than the permission, not a refusal.

command()

command(name: string, handler: (ctx: CommandContext) => void | Promise<void>, options: CommandOptions = {}): this

Register a command. Later registrations of the same name replace earlier.

start()

start(): Promise<ServerInfo>

Connect, join, and resolve once the server has said who this bot is.

On a first run against a server that has not approved it, this does not resolve — the bot is waiting at the door, which is a state and not a failure. Listen for waiting, and for ready when somebody answers.

stop()

stop(): Promise<void>

Leave, and stop reconnecting.

send()

send(conversationId: string, text: string): Promise<void>

Post in a channel.

Throws before sending anything if the bot lacks send_messages, naming the permission. The server would refuse it anyway; failing here means the stack trace points at the call rather than at a socket handler.

react()

react(conversationId: string, messageId: string, reactionSrc: string): Promise<void>

delete()

delete(conversationId: string, messageId: string, opts: { own?: boolean } = {}): Promise<void>

Delete a message.

Its own is delete_own_messages; anybody else's is manage_messages. The caller says which it is, because the bot does not necessarily know who sent a message it was handed.

fetch()

fetch(conversationId: string, limit = 50): Promise<void>

Ask for the last N messages in a channel. Answered on the message event.

GrytBotEvents

FieldTypeWhat it is
ready[ServerInfo]
message[Message]
members[Member[]]
channels[Channel[]]
error[Error]Something the server refused. Always worth logging; often a permission.
waiting[string]Turned away pending approval. Not an error — see the note in wire.
disconnected[string]

GrytBotOptions

FieldTypeWhat it is
hoststringchat.example.com, or localhost:5001. Scheme optional.
nickname?stringWhat the member list will call it.
identityPath?stringWhere the key lives. The file is the bot — see identity.ts.
identity?BotIdentityAn already-loaded identity, if you keep the key somewhere of your own.
wants?string[]Sent once, the first time it turns up, and shown to whoever approves it. Ask for the least that works. Fixed from then on. A later run declaring more gets the answer to the question the first one asked — the run asking for more may not be yours.
description?stringOne line, shown beside the ask. Say what the bot is for.
botToken?stringA token from a registration an operator set up in advance. The unattended path: no approval to wait for, because the approving already happened. Single-use — the first bot to present it becomes that registration.
prefix?stringThe command prefix. Set to "" to turn the router off entirely.
helpCommand?booleanWhether to answer help with a listing. On by default.
secure?booleanForce http/https rather than guessing from the host.

parseCommand

Which command a message invokes, if any.

Case-insensitive on the command word, because somebody will type !Help and being right about it helps nobody.

parseCommand(text: string, prefix: string): { name: string; rest: string } | null

splitArgs

splitArgs(rest: string): string[]

CommandContext

FieldTypeWhat it is
messageMessageThe message that invoked it.
reststringEverything after the command word, trimmed. Empty string, never null.
argsstring[]rest split on whitespace, with empties dropped.
reply(text: string): Promise<void>Reply in the channel the command came from.
react(emoji: string): Promise<void>React to the message that invoked it.

CommandOptions

FieldTypeWhat it is
description?stringOne line, for the help listing.
requires?Permission[]Permissions the bot needs before this command is worth offering. Checked before the handler runs, so a command that replies is skipped outright on a server where the bot may not post — rather than running, failing at the socket, and leaving whoever typed it watching nothing happen. This is about the bot, not about the person who typed it: what they may do is the server's business and it is already enforcing it.

RegisteredCommand

FieldTypeWhat it is
namestring
handler(ctx: CommandContext) => void | Promise<void>

createIdentity

Mint a new identity. The bot this belongs to has never been seen anywhere.

createIdentity(): Promise<{ identity: BotIdentity; privateJwk: JWK; }>

loadIdentity

The second run must be the same bot: same id, same role, same history. A key generated per start arrives as a new member every time.

Written 0o600 — anyone who can read this file can be this bot.

loadIdentity(path: string): Promise<BotIdentity>

PERMISSIONS_BEFORE_CATALOGUE

Stands in for the catalogue on a server too old to publish one, so an absent permission is not read as a refusal.

Frozen. It describes a release that has already happened, and never grows.

PERMISSIONS_BEFORE_CATALOGUE: readonly Permission[] = [ "send_messages", "attach_files", "add_reactions", "join_voice", "speak", "share_video", "share_screen", "change_nickname", "change_avatar", "create_invite", "manage_invites", "manage_messages", "kick_members", "ban_members", "mute_members", "manage_reports", "manage_join_requests", "manage_channels", "manage_emojis", "manage_webhooks", "manage_roles", "manage_server", "view_audit_log", ]

BotIdentity

FieldTypeWhat it is
subjectstringThe id this bot will be known by on every server. Derived from the key.
certificate(): Promise<string>A certificate that vouches for itself, valid for an hour.
assertion(audience: string, nonce: string): Promise<string>Proof, bound to one server's challenge, that this bot holds the key.

Attachment

FieldTypeWhat it is
file_idstring
mimestring | null
sizenumber | null
original_namestring | null
widthnumber | null
heightnumber | null
has_thumbnailboolean

Channel

FieldTypeWhat it is
idstring
namestring
type"text" | "voice"

ServerRefusal

Why the server refused something.

The machine-readable half is error, which is what the server actually sends; code is accepted too because it is the name half of this SDK reached for first and getting it wrong turned "waiting to be approved" into a crash.

FieldTypeWhat it is
error?string
code?string
message?string
permission?stringNamed when the refusal was a permission.

Member

FieldTypeWhat it is
serverUserIdstring
nicknamestring
rolestring
status"online" | "in_voice" | "afk" | "offline"
avatarFileIdstring | null

Message

FieldTypeWhat it is
conversationIdstring
messageIdstring
senderServerUserIdstring
senderNicknamestring | null
textstring | null
attachmentsAttachment[]
createdAtDate
editedAtDate | null
replyToMessageIdstring | null
isSystembooleanTrue for the "X joined the server" kind of message, which has no sender.
isOwnbooleanTrue when this bot sent it. Handlers are not called for these.

Permission

A permission id. The server owns the list; see GrytBot.permissions.

export type Permission = string;

ServerInfo

FieldTypeWhat it is
serverIdstring
namestring
descriptionstring
permissionsPermission[]What this bot may do here. Empty until the server has said.
rolestringThe role this bot holds.

On this page