server

package
v0.0.0-...-09e782f Latest Latest
Warning

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

Go to latest
Published: Apr 2, 2026 License: MIT Imports: 33 Imported by: 0

Documentation

Index

Constants

View Source
const (
	EventMessage                 = "message"
	EventChatCreated             = "chat_created"
	EventAddedToChat             = "added_to_chat"
	EventUserJoinedToChat        = "user_joined_to_chat"
	EventDeletedFromChat         = "deleted_from_chat"
	EventLeftFromChat            = "left_from_chat"
	EventChatDeletedByUser       = "chat_deleted_by_user"
	EventCTSLogin                = "cts_login"
	EventCTSLogout               = "cts_logout"
	EventEdit                    = "event_edit"
	EventSmartAppEvent           = "smartapp_event"
	EventInternalBotNotification = "internal_bot_notification"
	EventConferenceCreated       = "conference_created"
	EventConferenceDeleted       = "conference_deleted"
	EventCallStarted             = "call_started"
	EventCallEnded               = "call_ended"
	EventNotificationCallback    = "notification_callback"
)

BotX callback event type constants.

View Source
const DefaultAlertmanagerTemplate = `{{ if eq .Status "firing" }}` + "\U0001F525" + ` FIRING{{ else }}` + "\u2705" + ` RESOLVED{{ end }} [{{ index .GroupLabels "alertname" }}]
{{ range .Alerts }}
{{ if eq .Status "firing" }}` + "\U0001F534" + `{{ else }}` + "\U0001F7E2" + `{{ end }} {{ index .Labels "alertname" }} — {{ index .Annotations "summary" }}
  Severity: {{ index .Labels "severity" }}
  Instance: {{ index .Labels "instance" }}
  Started:  {{ .StartsAt.Format "2006-01-02 15:04:05" }}{{ if ne .Status "firing" }}
  Ended:    {{ .EndsAt.Format "2006-01-02 15:04:05" }}{{ end }}
{{ end }}`

DefaultAlertmanagerTemplate is the built-in template for formatting alerts.

View Source
const DefaultGrafanaTemplate = `{{ if eq .Status "firing" }}` + "\U0001F525" + ` FIRING{{ else }}` + "\u2705" + ` RESOLVED{{ end }} {{ .Title }}
{{ range .Alerts }}
{{ if eq .Status "firing" }}` + "\U0001F534" + `{{ else }}` + "\U0001F7E2" + `{{ end }} {{ index .Labels "alertname" }} — {{ index .Annotations "summary" }}
  Folder:   {{ index .Labels "grafana_folder" }}
  Started:  {{ .StartsAt.Format "2006-01-02 15:04:05" }}{{ if ne .Status "firing" }}
  Ended:    {{ .EndsAt.Format "2006-01-02 15:04:05" }}{{ end }}{{ if .DashboardURL }}
  Dashboard: {{ .DashboardURL }}{{ end }}{{ if .PanelURL }}
  Panel:     {{ .PanelURL }}{{ end }}{{ if .SilenceURL }}
  Silence:   {{ .SilenceURL }}{{ end }}
{{ end }}`

DefaultGrafanaTemplate is the built-in template for formatting Grafana alerts.

Variables

This section is empty.

Functions

func AuthBot

func AuthBot(ctx context.Context) string

AuthBot returns the bot name bound by X-Bot-Signature authentication. Empty string means no bot was bound (API-key auth or single-bot mode).

func JWTAud

func JWTAud(ctx context.Context) string

JWTAud returns the verified JWT audience (bot ID) from the request context. Returns empty string if JWT verification was not performed or aud is not set.

func KeyName

func KeyName(ctx context.Context) string

KeyName returns the API key name from the request context.

func ParseAlertmanagerTemplate

func ParseAlertmanagerTemplate(tmplStr string) (*template.Template, error)

ParseAlertmanagerTemplate compiles a Go text/template for alertmanager messages.

func ParseGrafanaTemplate

func ParseGrafanaTemplate(tmplStr string) (*template.Template, error)

ParseGrafanaTemplate compiles a Go text/template for Grafana messages.

Types

type AlertItem

type AlertItem struct {
	Status       string            `json:"status"`
	Labels       map[string]string `json:"labels"`
	Annotations  map[string]string `json:"annotations"`
	StartsAt     time.Time         `json:"startsAt"`
	EndsAt       time.Time         `json:"endsAt"`
	GeneratorURL string            `json:"generatorURL"`
}

AlertItem is a single alert within the webhook payload.

type AlertmanagerConfig

type AlertmanagerConfig struct {
	DefaultChatID   string   // default target chat UUID or alias (may be empty)
	ErrorSeverities []string // severities that map to status "error"
	Template        *template.Template
	// FallbackChatID is resolved at startup from the config's chats section
	// when there is exactly one chat alias configured. Empty otherwise.
	FallbackChatID string
}

AlertmanagerConfig holds settings for the alertmanager webhook endpoint.

type AlertmanagerWebhook

type AlertmanagerWebhook struct {
	Version           string            `json:"version"`
	GroupKey          string            `json:"groupKey"`
	Status            string            `json:"status"` // "firing" | "resolved"
	Receiver          string            `json:"receiver"`
	GroupLabels       map[string]string `json:"groupLabels"`
	CommonLabels      map[string]string `json:"commonLabels"`
	CommonAnnotations map[string]string `json:"commonAnnotations"`
	ExternalURL       string            `json:"externalURL"`
	Alerts            []AlertItem       `json:"alerts"`
}

AlertmanagerWebhook is the JSON payload from Alertmanager.

type CallbackCommand

type CallbackCommand struct {
	Body        string          `json:"body"`
	CommandType string          `json:"command_type,omitempty"`
	Data        json.RawMessage `json:"data,omitempty"`
	Metadata    json.RawMessage `json:"metadata,omitempty"`
}

CallbackCommand holds the command part of a callback payload.

type CallbackFrom

type CallbackFrom struct {
	UserHUID    string `json:"user_huid,omitempty"`
	GroupChatID string `json:"group_chat_id"`
	ChatType    string `json:"chat_type,omitempty"`
	Host        string `json:"host,omitempty"`
	AdChat      bool   `json:"ad_chat,omitempty"`
	AdGroup     bool   `json:"ad_group,omitempty"`
}

CallbackFrom holds sender information in a callback payload.

type CallbackHandler

type CallbackHandler interface {
	// Type returns the handler type name (e.g. "exec", "webhook").
	Type() string
	// Handle processes a callback event. payload is the raw JSON body.
	Handle(ctx context.Context, event string, payload []byte) error
}

CallbackHandler processes a BotX callback event.

type CallbackOption

type CallbackOption func(*callbackOptions)

CallbackOption configures callback handling.

func WithCallbackHandler

func WithCallbackHandler(handler CallbackHandler) CallbackOption

WithCallbackHandler registers a custom CallbackHandler that can be referenced by its Type() name in callback rules. Custom handlers take precedence over the built-in exec and webhook handlers.

func WithCallbackSecretLookup

func WithCallbackSecretLookup(fn func(botID string) (string, error)) CallbackOption

WithCallbackSecretLookup sets the function used to look up bot secrets for JWT verification in callback endpoints. Required when verify_jwt is enabled.

type CallbackPayload

type CallbackPayload struct {
	SyncID       string          `json:"sync_id"`
	Command      CallbackCommand `json:"command"`
	From         CallbackFrom    `json:"from"`
	BotID        string          `json:"bot_id"`
	ProtoVersion int             `json:"proto_version,omitempty"`
	Attachments  json.RawMessage `json:"attachments,omitempty"`
	AsyncFiles   json.RawMessage `json:"async_files,omitempty"`
	Entities     json.RawMessage `json:"entities,omitempty"`
}

CallbackPayload represents a BotX API v4 POST /command request body.

type CallbackRouter

type CallbackRouter struct {
	// contains filtered or unexported fields
}

CallbackRouter matches callback events to their configured handlers.

func NewCallbackRouter

func NewCallbackRouter(events [][]string, asyncFlags []bool, handlers map[int]CallbackHandler) (*CallbackRouter, error)

NewCallbackRouter creates a CallbackRouter from config rules and a handler registry. handlerRegistry maps rule index to a CallbackHandler instance.

func (*CallbackRouter) Route

func (r *CallbackRouter) Route(event string) []matchedRule

Route returns all rules that match the given event, in declaration order. A rule matches if its events list contains the exact event name or the wildcard "*".

type ChatResolveResult

type ChatResolveResult struct {
	ChatID string
	Bot    string // from chat config, may be empty
}

ChatResolveResult holds the resolved chat UUID and optional bound bot name.

type ChatResolver

type ChatResolver func(chatID string) (ChatResolveResult, error)

ChatResolver resolves a chat alias to a UUID and optional bound bot.

type Config

type Config struct {
	Listen             string
	BasePath           string
	Keys               []ResolvedKey
	AllowBotSecretAuth bool
	BotSignatures      map[string]string // signature -> bot name (multi-bot) or "" (single-bot)
	BotNames           []string          // available bot names; if len > 1, bot is required in requests
	SingleBotName      string            // name of the single bot (when not multi-bot); used to reject mismatched chat bindings
	DefaultChatAlias   string            // alias of the chat marked as default; used when chat_id is omitted
	EnableDocs         bool              // serve /docs (Swagger UI) and /docs/openapi.yaml
	ExternalURL        string            // public URL for OpenAPI docs server variable
	AppVersion         string            // application version (from -ldflags), replaces version in OpenAPI spec
	AsyncMode          bool              // when true, /send enqueues instead of sending directly
	DefaultRoutingMode string            // default routing mode for async: direct, catalog, mixed
	MaxFileSize        int64             // max file size in bytes for async mode (0 = default 1MB)
}

Config holds the server runtime configuration.

type ExecHandler

type ExecHandler struct {
	// contains filtered or unexported fields
}

ExecHandler runs an external command to handle callback events. The callback payload JSON is passed via stdin.

func NewExecHandler

func NewExecHandler(command string, timeout time.Duration) *ExecHandler

NewExecHandler creates an ExecHandler that runs the given command with the specified timeout. A zero timeout means no deadline.

func (*ExecHandler) Handle

func (h *ExecHandler) Handle(ctx context.Context, event string, payload []byte) error

Handle runs the configured command, passing payload as JSON on stdin. It sets environment variables with callback metadata for the child process.

func (*ExecHandler) Type

func (h *ExecHandler) Type() string

Type returns "exec".

type FilePayload

type FilePayload struct {
	Name string `json:"name"`
	Data string `json:"data"` // base64
}

FilePayload represents a file attachment in the JSON request.

type GrafanaAlertItem

type GrafanaAlertItem struct {
	Status       string            `json:"status"`
	Labels       map[string]string `json:"labels"`
	Annotations  map[string]string `json:"annotations"`
	StartsAt     time.Time         `json:"startsAt"`
	EndsAt       time.Time         `json:"endsAt"`
	GeneratorURL string            `json:"generatorURL"`
	Fingerprint  string            `json:"fingerprint"`
	SilenceURL   string            `json:"silenceURL"`
	DashboardURL string            `json:"dashboardURL"`
	PanelURL     string            `json:"panelURL"`
	ImageURL     string            `json:"imageURL"`
	Values       map[string]any    `json:"values"`
}

GrafanaAlertItem is a single alert within the Grafana webhook payload.

type GrafanaConfig

type GrafanaConfig struct {
	DefaultChatID string   // default target chat UUID or alias (may be empty)
	ErrorStates   []string // states that map to status "error"
	Template      *template.Template
	// FallbackChatID is resolved at startup from the config's chats section
	// when there is exactly one chat alias configured. Empty otherwise.
	FallbackChatID string
}

GrafanaConfig holds settings for the Grafana webhook endpoint.

type GrafanaWebhook

type GrafanaWebhook struct {
	Receiver          string             `json:"receiver"`
	Status            string             `json:"status"` // "firing" | "resolved"
	OrgID             int                `json:"orgId"`
	Alerts            []GrafanaAlertItem `json:"alerts"`
	GroupLabels       map[string]string  `json:"groupLabels"`
	CommonLabels      map[string]string  `json:"commonLabels"`
	CommonAnnotations map[string]string  `json:"commonAnnotations"`
	ExternalURL       string             `json:"externalURL"`
	Version           string             `json:"version"`
	GroupKey          string             `json:"groupKey"`
	TruncatedAlerts   int                `json:"truncatedAlerts"`
	Title             string             `json:"title"`
	State             string             `json:"state"` // "alerting" | "ok" | "no_data" | "pending"
	Message           string             `json:"message"`
}

GrafanaWebhook is the JSON payload from Grafana alerting webhook.

type NotificationCallbackPayload

type NotificationCallbackPayload struct {
	SyncID    string          `json:"sync_id"`
	Status    string          `json:"status"`
	Result    json.RawMessage `json:"result,omitempty"`
	Reason    string          `json:"reason,omitempty"`
	Errors    json.RawMessage `json:"errors,omitempty"`
	ErrorData json.RawMessage `json:"error_data,omitempty"`
}

NotificationCallbackPayload represents a BotX API v4 POST /notification/callback request body.

type Option

type Option func(*Server)

Option configures optional server features.

func WithAPM

func WithAPM(p apm.Provider) Option

WithAPM sets the APM provider for request tracing.

func WithAlertmanager

func WithAlertmanager(cfg *AlertmanagerConfig) Option

WithAlertmanager enables the alertmanager webhook endpoint.

func WithBotMentionsResolvers

func WithBotMentionsResolvers(m map[string]mentions.UserResolver) Option

WithBotMentionsResolvers sets per-bot user resolvers for multi-bot setups where bots may reside on different eXpress hosts. When the request specifies a bot name, the corresponding resolver is used instead of the default one.

func WithCallbacks

func WithCallbacks(cfg config.CallbacksConfig, opts ...CallbackOption) Option

WithCallbacks enables callback endpoints (POST /command and POST /notification/callback). It creates a CallbackRouter from the config rules and registers handlers.

func WithConfigInfo

func WithConfigInfo(bots []config.BotEntry, chats []config.ChatEntry) Option

WithConfigInfo sets the bot and chat entries for the config endpoints.

func WithErrTracker

func WithErrTracker(t errtrack.Tracker) Option

WithErrTracker sets the error tracker for panic/error capture.

func WithGrafana

func WithGrafana(cfg *GrafanaConfig) Option

WithGrafana enables the Grafana webhook endpoint.

func WithMentionsResolver

func WithMentionsResolver(r mentions.UserResolver) Option

WithMentionsResolver sets the user resolver used by the inline mentions parser. When nil, email mentions will produce lookup errors but the message will still be sent.

type OptsPayload

type OptsPayload struct {
	Silent   bool `json:"silent"`
	Stealth  bool `json:"stealth"`
	ForceDND bool `json:"force_dnd"`
	NoNotify bool `json:"no_notify"`
}

OptsPayload holds delivery options.

type ResolvedKey

type ResolvedKey struct {
	Name string
	Key  string
}

ResolvedKey is an API key with its secret resolved.

type SendFunc

type SendFunc func(ctx context.Context, req *SendPayload) (syncID string, err error)

SendFunc sends a message via the BotX API. The server calls this for each request.

type SendPayload

type SendPayload struct {
	Bot         string          `json:"bot,omitempty"`
	ChatID      string          `json:"chat_id"`
	Message     string          `json:"message"`
	File        *FilePayload    `json:"file,omitempty"`
	Status      string          `json:"status"`
	Opts        *OptsPayload    `json:"opts,omitempty"`
	Metadata    json.RawMessage `json:"metadata,omitempty"`
	Mentions    json.RawMessage `json:"mentions,omitempty"`
	RoutingMode string          `json:"routing_mode,omitempty"` // async mode: direct, catalog, mixed
	BotID       string          `json:"bot_id,omitempty"`       // async mode: bot UUID for direct routing
	NoParse     bool            `json:"-"`                      // internal: skip mentions parsing (set by handler for async mode)
}

SendPayload is the parsed request for sending a message.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is the HTTP server for express-botx.

func New

func New(cfg Config, sendFn SendFunc, chatResolver ChatResolver, opts ...Option) *Server

New creates a Server with the given configuration.

func (*Server) Run

func (s *Server) Run(ctx context.Context) error

Run starts the server and blocks until ctx is cancelled. It performs graceful shutdown.

type WebhookHandler

type WebhookHandler struct {
	// contains filtered or unexported fields
}

WebhookHandler sends callback events as HTTP POST requests to a configured URL.

func NewWebhookHandler

func NewWebhookHandler(url string, timeout time.Duration) *WebhookHandler

NewWebhookHandler creates a WebhookHandler that POSTs callback payloads to the given URL with the specified timeout. A zero timeout means no deadline.

func (*WebhookHandler) Handle

func (h *WebhookHandler) Handle(ctx context.Context, event string, payload []byte) error

Handle sends the callback payload as an HTTP POST to the configured URL. It sets Content-Type, X-Express-Event, and X-Express-Sync-ID headers.

func (*WebhookHandler) Type

func (h *WebhookHandler) Type() string

Type returns "webhook".

Jump to

Keyboard shortcuts

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