core

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 29, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package core holds botbooter's platform-agnostic engine: the Bot type, its command/middleware dispatch, and the connection lifecycle.

Index

Constants

This section is empty.

Variables

View Source
var ErrAlreadyConnected = errors.New("botbooter: already connected")

ErrAlreadyConnected is returned by Connect when the Bot is already connected.

View Source
var ErrUnknownBotType = errors.New("botbooter: unknown bot type")

ErrUnknownBotType is returned by Bot methods when the Bot has no adapter.

Functions

func AdapterAs added in v0.2.0

func AdapterAs[T any](b *Bot) (T, bool)

AdapterAs returns the Bot's adapter as T, reporting whether it is that type. Adapter packages use it to recover their concrete adapter — and the platform client it holds — from a *Bot, so callers get typed access without core importing any platform SDK.

Types

type Adapter

type Adapter interface {
	Connect(ctx context.Context, deps AdapterDeps) error
	Disconnect() error
	Send(ctx context.Context, channelID, text string) error
	Attachments(m *Message) ([]Attachment, error)
}

Adapter is the platform-specific half of a Bot. The Bot drives it through this interface, so the core has no compile-time dependency on any platform.

type AdapterDeps

type AdapterDeps struct {
	Dispatch   func(ctx context.Context, m *Message)
	Done       func(err error)
	Disconnect func() error
}

AdapterDeps is the set of callbacks an Adapter uses to talk back to the Bot.

type Attachment

type Attachment struct {
	IsImage   bool
	URL       string
	ExtraData any
}

Attachment is a platform-agnostic file attached to a message.

type AttachmentResolver added in v0.2.0

type AttachmentResolver interface {
	ResolveAttachmentURL(ctx context.Context, att Attachment) (string, error)
}

AttachmentResolver is an OPTIONAL capability an Adapter may implement to turn an Attachment into a downloadable URL. It is deliberately NOT part of the mandatory Adapter interface: adapters whose Attachment.URL is already usable implement nothing and ride the passthrough in Bot.ResolveAttachmentURL.

type Bot

type Bot struct {
	BotType BotType
	// contains filtered or unexported fields
}

Bot is the platform-agnostic chat bot. A Bot is safe for concurrent use.

func New

func New(botType BotType, adapter Adapter) *Bot

New creates a Bot of the given type backed by adapter.

func (*Bot) AddHandler

func (b *Bot) AddHandler(cmd Command) error

AddHandler registers cmd, compiling its Pattern and returning an error if it is not valid. Commands are matched in registration order, first match wins.

func (*Bot) AddMiddleware

func (b *Bot) AddMiddleware(middleware Middleware)

AddMiddleware appends middleware to the dispatch chain, run in registration order.

func (*Bot) Connect

func (b *Bot) Connect(ctx context.Context) error

Connect starts the adapter's event loop and returns without blocking. It returns ErrAlreadyConnected if a connection is already active, ErrUnknownBotType if the Bot has no adapter, or any error from the adapter's own Connect.

func (*Bot) Disconnect

func (b *Bot) Disconnect() error

Disconnect tears down the active connection: it cancels the run context and runs the adapter's Disconnect exactly once. It is safe to call when not connected, returning ErrUnknownBotType only if the Bot has no adapter.

func (*Bot) GetAttachments

func (b *Bot) GetAttachments(message *Message) ([]Attachment, error)

GetAttachments returns the platform-agnostic attachments of message.

func (*Bot) HandleFunc

func (b *Bot) HandleFunc(pattern string, handler CommandHandler) error

HandleFunc is a convenience wrapper around AddHandler.

func (*Bot) ResolveAttachmentURL added in v0.2.0

func (b *Bot) ResolveAttachmentURL(ctx context.Context, att Attachment) (string, error)

ResolveAttachmentURL returns a downloadable URL for att — the unified cross-platform entry point. If the Bot's adapter implements AttachmentResolver the call is delegated in full (the adapter owns the result, including ("", nil) meaning "nothing to resolve"); otherwise att.URL is returned verbatim. It returns ErrUnknownBotType if the Bot has no adapter. An empty string with a nil error means "not resolvable", not a failure.

The result is consumed DIFFERENTLY per platform and is not uniformly fetchable with a bare GET:

  • Discord: att.URL is already a signed CDN link (~24h), returned as-is via the passthrough; fetch it with a plain GET and consume promptly.
  • Slack: NOT directly fetchable — download via the Slack Web API client (SlackClient(b).GetFileContext), which injects the bot token.
  • Telegram: a plain GET on a SECRET, ~1h URL that embeds the bot token in plaintext — never log or cache it. Each successful Telegram resolve logs a warning, suppressible via the BOTBOOTER_TELEGRAM_SUPPRESS_URL_WARNING environment variable.
  • WhatsApp: NOT directly fetchable — GET it with an Authorization: Bearer <token> header (the Cloud API token used to send). Short-lived; consume promptly.
  • CLI: a local filesystem path (open with os.Open), not an HTTP URL.

func (*Bot) Run

func (b *Bot) Run(ctx context.Context) error

Run connects the Bot and blocks until ctx is canceled or the event loop ends, then disconnects. A clean shutdown via ctx cancellation returns nil rather than ctx.Err(), so callers can safely do log.Fatal(bot.Run(ctx)).

func (*Bot) SendMessage

func (b *Bot) SendMessage(channelID, text string) error

SendMessage sends text to channelID using a background context.

func (*Bot) SendMessageContext

func (b *Bot) SendMessageContext(ctx context.Context, channelID, text string) error

SendMessageContext sends text to channelID, honoring ctx for cancellation.

func (*Bot) SetUnknownCommandHandler

func (b *Bot) SetUnknownCommandHandler(handler CommandHandler)

SetUnknownCommandHandler sets the handler invoked when a message matches no registered command; if unset, unmatched messages are ignored.

func (*Bot) Start

func (b *Bot) Start() error

Start runs the Bot until the process receives an interrupt or SIGTERM.

type BotType

type BotType int

BotType identifies the messaging platform a Bot is connected to.

const (
	SlackBotType BotType = iota
	DiscordBotType
	CLIBotType
	TelegramBotType
	WhatsAppBotType
)

The supported bot types.

func (BotType) String

func (t BotType) String() string

type CLIMessage

type CLIMessage struct {
	Text        string
	Attachments []Attachment
}

CLIMessage is the raw payload of a message read from the CLI adapter.

type Command

type Command struct {
	Pattern string
	Handler CommandHandler
	// contains filtered or unexported fields
}

Command pairs a regular-expression Pattern with the Handler to run on a match.

type CommandHandler

type CommandHandler func(ctx context.Context, b *Bot, m *Message)

CommandHandler handles a dispatched message for a matched command.

type Message

type Message struct {
	ID               string
	UserID           string
	AuthorName       string
	ChannelID        string
	Content          string
	Timestamp        time.Time
	ReplyToID        string
	MentionedUserIDs []string

	Raw any
}

Message is a platform-agnostic incoming message handed to command handlers. UserID, ChannelID and Content are always set. The remaining normalized fields are best-effort: a platform that cannot supply one leaves it at its zero value. Raw carries the originating platform's untouched event; read it with the matching typed accessor (e.g. botbooter.DiscordRawEvent).

MentionedUserIDs holds mentioned user ids and is best-effort per platform: Slack and Discord surface every mention, while Telegram contributes only text_mention entities (a plain @username carries no numeric id and is omitted).

type Middleware

type Middleware func(ctx context.Context, b *Bot, m *Message, next CommandHandler)

Middleware wraps message dispatch; it must call next to continue the chain.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL