Documentation
¶
Overview ¶
Package core holds botbooter's platform-agnostic engine: the Bot type, its command/middleware dispatch, and the connection lifecycle.
Index ¶
- Variables
- func AdapterAs[T any](b *Bot) (T, bool)
- type Adapter
- type AdapterDeps
- type Attachment
- type AttachmentResolver
- type Bot
- func (b *Bot) AddHandler(cmd Command) error
- func (b *Bot) AddMiddleware(middleware Middleware)
- func (b *Bot) Connect(ctx context.Context) error
- func (b *Bot) Disconnect() error
- func (b *Bot) GetAttachments(message *Message) ([]Attachment, error)
- func (b *Bot) HandleFunc(pattern string, handler CommandHandler) error
- func (b *Bot) ResolveAttachmentURL(ctx context.Context, att Attachment) (string, error)
- func (b *Bot) Run(ctx context.Context) error
- func (b *Bot) SendMessage(channelID, text string) error
- func (b *Bot) SendMessageContext(ctx context.Context, channelID, text string) error
- func (b *Bot) SetUnknownCommandHandler(handler CommandHandler)
- func (b *Bot) Start() error
- type BotType
- type CLIMessage
- type Command
- type CommandHandler
- type Message
- type Middleware
Constants ¶
This section is empty.
Variables ¶
var ErrAlreadyConnected = errors.New("botbooter: already connected")
ErrAlreadyConnected is returned by Connect when the Bot is already connected.
var ErrUnknownBotType = errors.New("botbooter: unknown bot type")
ErrUnknownBotType is returned by Bot methods when the Bot has no adapter.
Functions ¶
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 ¶
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 (*Bot) AddHandler ¶
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 ¶
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 ¶
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
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 ¶
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 ¶
SendMessage sends text to channelID using a background context.
func (*Bot) SendMessageContext ¶
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.
type BotType ¶
type BotType int
BotType identifies the messaging platform a Bot is connected to.
The supported bot types.
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 ¶
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.