Gryt
Build on Gryt

Bot API

Everything @gryt/bot exports, generated from the source

Generated from the source and regenerated by CI, so it cannot fall behind the code. Editing this page by hand gets the edit wiped on the next run — change what the generator reads instead.

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 and no bypass, so what it may do is what its role says.

can()

can(permission: Permission): boolean

False before ready. 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 it does not resolve: the bot is waiting at the door. Listen for waiting, then ready.

stop()

stop(): Promise<void>

Leave, and stop reconnecting.

send()

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

Post in a channel. Throws before sending if the bot lacks send_messages, naming the permission, so the stack trace points at the call rather than 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, and the caller says which, because the bot may not know who sent it.

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. Fixed from then on: a later run declaring more gets the answer to the question the first one asked.
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: no approval to wait for. 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. About the bot, not the person: what they may do is the server's business.

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. 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.

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; code is accepted too, because this SDK reached for that name first and the mistake read as 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