glyde

glyde is a sans-IO Discord library that brings its own IO. glyde/gateway is the protocol state machine; this module is the supervision tree already wired to it, so a bot is the handlers and nothing else.

import gleam/bool
import glyde
import glyde/intents
import glyde/message

pub fn main() -> Nil {
  glyde.new(token:, intents: intents.new([intents.GuildMessages]))
  |> glyde.on_message(fn(api, msg) {
    use <- bool.guard(msg.content != "!ping", Nil)
    let _ = message.reply(api, msg, message.text("pong!"))
    Nil
  })
  |> glyde.run
}

Each event is handed to a fresh process under a supervisor, so a slow or crashing handler never holds up the next one. An endpoint call blocks that one process on the rate limiter and the network; the shard keeps reading.

glyde/client is the layer below, for driving the machine yourself.

Types

pub type Api =
  api.Api

A bot before it starts. Opaque and a value: every builder gives back a new one.

pub opaque type Bot
pub type Call(a) =
  rest.Call(a)
pub type CallFailure =
  api.CallFailure
pub type ChannelId =
  id.Id(id.Channel)
pub type Event =
  event.Event
pub type Failure =
  error.ApiError
pub type Ready =
  ready.Ready
pub type Status =
  status.Status

The platform half: a socket, an HTTP client and a clock.

pub type Transport =
  transport.Transport

Values

pub const api_version: Int

The Discord API version glyde speaks, for both the gateway and REST.

pub fn new(
  token secret: String,
  intents intents: intents.Intents,
) -> Bot

One shard, no compression, a real socket, and a line on stderr when something goes wrong.

pub fn on_event(
  bot: Bot,
  handler: fn(api.Api, event.Event) -> a,
) -> Bot

Every dispatch, decoded. One glyde does not model arrives as event.Raw with Discord’s payload untouched.

pub fn on_interaction(
  bot: Bot,
  handler: fn(api.Api, interaction.Interaction) -> a,
) -> Bot

Every INTERACTION_CREATE: slash commands, buttons, autocomplete.

pub fn on_message(
  bot: Bot,
  handler: fn(api.Api, message.Message) -> a,
) -> Bot

Every MESSAGE_CREATE. Add as many as you like; each runs in the same handler process for that event, in the order added.

pub fn on_ready(
  bot: Bot,
  handler: fn(api.Api, ready.Ready) -> a,
) -> Bot

READY, which carries the bot’s own user and the guilds it is in. Sent again after every fresh identify, so this is not once per process.

pub fn on_status(
  bot: Bot,
  handler: fn(status.Status) -> a,
) -> Bot

Watch the runtime: dials, reconnects, halts, failed sends, diagnostics. Runs on the shard process (or the limiter for Paced), not a handler process, so keep it cheap.

pub fn run(bot: Bot) -> Nil

Start the tree and block until the shard halts. What main calls: a bad token or disallowed intents come back as Nil rather than a hung process.

pub fn start(bot: Bot) -> Result(process.Pid, actor.StartError)

Build the supervision tree and start it. Returns the top supervisor’s pid, so the caller can put it under one of their own or monitor it.

pub fn with_transport(
  bot: Bot,
  transport: transport.Transport,
) -> Bot

Run over a socket, a clock and an HTTP client of your own. The rate limiter sits around request, so yours is paced without knowing it.

Search Document