botsfw

package
v0.77.8 Latest Latest
Warning

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

Go to latest
Published: Jul 27, 2026 License: Apache-2.0 Imports: 20 Imported by: 7

Documentation

Index

Constants

View Source
const (
	// MessageTextBotDidNotUnderstandTheCommand is an i18n constant
	MessageTextBotDidNotUnderstandTheCommand = "MessageTextBotDidNotUnderstandTheCommand"

	// MessageTextOopsSomethingWentWrong is an i18n constant
	MessageTextOopsSomethingWentWrong = "MessageTextOopsSomethingWentWrong"
)
View Source
const (
	// BotAPISendMessageOverHTTPS indicates message should be sent over HTTPS
	BotAPISendMessageOverHTTPS = botmsg.BotAPISendMessageChannel("https")

	// BotAPISendMessageOverResponse indicates message should be sent in HTTP response
	BotAPISendMessageOverResponse = botmsg.BotAPISendMessageChannel("response")
)
View Source
const DefaultTitle = "" //

DefaultTitle key

View Source
const ShortTitle = "short_title"

ShortTitle key

Variables

View Source
var EnvLocal = "local" // TODO: Consider adding this to init interface of setting config values
View Source
var EnvProduction = "production" // TODO: Consider adding this to init interface of setting config values
View Source
var ErrCallbackQueryAcknowledgementUnsupported = errors.New("callback query acknowledgement is not supported")

ErrCallbackQueryAcknowledgementUnsupported is returned when the current platform adapter cannot acknowledge callback queries before a handler returns.

View Source
var (
	// ErrEntityNotFound is returned if entity not found in storage
	ErrEntityNotFound = errors.New("bots-framework: no such entity")
)
View Source
var ErrNotImplemented = errors.New("not implemented")

ErrNotImplemented if some feature is not implemented yet

View Source
var ErrSendNotPermitted = errors.New("sending is not permitted right now")

ErrSendNotPermitted is the base for refusals returned by a SendGate.

Wrap it so callers can classify a refusal with errors.Is without depending on a specific platform's package:

fmt.Errorf("outside the 24h window: %w", botsfw.ErrSendNotPermitted)
View Source
var ErrUnknownBot = errors.New("unknown bot")
View Source
var IgnoreCommand = Command{
	Code: "bots.IgnoreCommand",
	Action: func(_ WebhookContext) (m botmsg.MessageFromBot, err error) {
		return
	},
	CallbackAction: func(_ WebhookContext, _ *url.URL) (m botmsg.MessageFromBot, err error) {
		return
	},
	TextAction: func(_ WebhookContext, _ string) (m botmsg.MessageFromBot, err error) {
		return
	},
	InlineQueryAction: func(_ WebhookContext, _ botinput.InlineQuery, _ *url.URL) (m botmsg.MessageFromBot, err error) {
		return
	},
	ChosenInlineResultAction: func(_ WebhookContext, _ botinput.ChosenInlineResult, _ *url.URL) (m botmsg.MessageFromBot, err error) {
		return
	},
}

IgnoreCommand is a command that does nothing

Functions

func AcknowledgeCallbackQuery added in v0.77.4

func AcknowledgeCallbackQuery(whc WebhookContext, text string, showAlert bool) error

AcknowledgeCallbackQuery immediately answers the callback query represented by whc. Long-running handlers should call it before doing network or AI work. The router observes the acknowledgement marker and does not send its normal fallback answer a second time.

func AssertFeatureScenario added in v0.77.1

func AssertFeatureScenario(s FeatureScenario, want FeatureScenarioExpectation) error

func CanSend added in v0.72.0

func CanSend(c context.Context, responder WebhookResponder, m botmsg.MessageFromBot) error

CanSend reports whether responder permits sending m right now.

Responders that do not implement SendGate always permit, so this is safe to call on any responder. Returns nil when the send may proceed.

func CommandTextNoTrans

func CommandTextNoTrans(title, icon string) string

CommandTextNoTrans returns a title for a command (pre-translated)

func GetEnv added in v0.76.1

func GetEnv(ctx context.Context, name string) string

GetEnv resolves name through the provider attached to ctx and returns an empty string when the name is not present.

func IsSendNotPermitted added in v0.72.0

func IsSendNotPermitted(err error) bool

IsSendNotPermitted reports whether err is a SendGate refusal.

func LookupEnv added in v0.76.1

func LookupEnv(ctx context.Context, name string) (value string, ok bool)

LookupEnv resolves name through the provider attached to ctx.

func NotFoundHandler

func NotFoundHandler(w http.ResponseWriter, _ *http.Request)

NotFoundHandler returns HTTP status code 404

func PingHandler

func PingHandler(w http.ResponseWriter, r *http.Request)

PingHandler returns 'Pong' back to user

func SetAccessGranted

func SetAccessGranted(whc WebhookContext, value bool) (err error)

SetAccessGranted marks current context as authenticated

func ValidateFeatureMounts added in v0.77.1

func ValidateFeatureMounts(mounts []FeatureMount) error

ValidateFeatureMounts fails before startup if mounted features would make routing ambiguous. This is deliberately separate from Router so existing bots can adopt feature descriptors incrementally.

func WasCallbackQueryAcknowledged added in v0.77.4

func WasCallbackQueryAcknowledged(whc WebhookContext) bool

WasCallbackQueryAcknowledged reports whether the current callback query was already answered explicitly by its handler.

func WithEnvProvider added in v0.76.1

func WithEnvProvider(ctx context.Context, provider EnvProvider) context.Context

WithEnvProvider returns a child context that resolves environment-backed runtime configuration through provider. It does not mutate process state.

Types

type AppContext added in v0.35.0

type AppContext interface {
	i18n.LocalesProvider
	GetTranslator(ctx context.Context) i18n.Translator
}

AppContext provides application-owned presentation services to bots-fw. Persistence is injected separately through BotSettings.Store.

type BotCommand added in v0.62.0

type BotCommand struct {
	Command     string `json:"command"`     // Text of the command; 1-32 characters. Can contain only lowercase English letters, digits and underscores.
	Description string `json:"description"` // Description of the command; 1-256 characters.
	IsEphemeral bool   `json:"is_ephemeral,omitempty"`
}

func OrderBotCommands added in v0.77.3

func OrderBotCommands(
	commands []BotCommand,
	order BotCommandOrder,
	pinnedCommands ...string,
) ([]BotCommand, error)

OrderBotCommands returns a copy arranged according to order. pinnedCommands is only valid with BotCommandOrderPinnedThenAlphabetical, and the supplied pin order is preserved.

func (BotCommand) Validate added in v0.62.0

func (v BotCommand) Validate() error

type BotCommandOrder added in v0.77.3

type BotCommandOrder string
const (
	// BotCommandOrderDeclared preserves the order in BotTranslations.Commands.
	BotCommandOrderDeclared BotCommandOrder = ""
	// BotCommandOrderAlphabetical orders all published commands by command code.
	BotCommandOrderAlphabetical BotCommandOrder = "alphabetical"
	// BotCommandOrderPinnedThenAlphabetical puts explicitly pinned commands
	// first and orders every remaining command by command code.
	BotCommandOrderPinnedThenAlphabetical BotCommandOrder = "pinned_then_alphabetical"
)

type BotContext

type BotContext struct {
	AppContext  AppContext
	BotHost     BotHost      // describes current bot app host environment
	BotSettings *BotSettings // keeps parameters of a bot that are static and are not changed in runtime
}

BotContext binds a bot to a specific hosting environment

func NewBotContext

func NewBotContext(botHost BotHost, botSettings *BotSettings) *BotContext

NewBotContext creates current bot host & settings

type BotContextProvider added in v0.35.0

type BotContextProvider interface {
	// GetBotContext returns BotContext by platformID & botID
	GetBotContext(ctx context.Context, platformID botsfwconst.Platform, botID string) (botContext *BotContext, err error)
}

BotContextProvider provides BotContext by platformID & botID

func NewBotContextProvider added in v0.35.0

func NewBotContextProvider(botHost BotHost, appContext AppContext, botSettingProvider BotSettingsProvider) BotContextProvider

type BotHost

type BotHost interface {

	// Context returns a context.Context for a request. We need this as some platforms (as Google App Engine Standard)
	// require usage of a context with a specific wrapper
	Context(r *http.Request) context.Context

	// GetHTTPClient returns HTTP client for current host
	// We need this as some platforms (as Google App Engine Standard) require setting http client in a specific way.
	GetHTTPClient(c context.Context) *http.Client
}

BotHost describes current bot app host environment

type BotInputProvider

type BotInputProvider interface {
	// Input returns a webhook input from a specific bot interface (Telegram, FB Messenger, Viber, etc.)
	Input() botinput.InputMessage
}

BotInputProvider provides an input from a specific bot interface (Telegram, FB Messenger, Viber, etc.)

type BotPlatform

type BotPlatform interface {

	// ID returns bot platform ID like 'telegram', 'fbmessenger', 'viber', etc.
	ID() string

	// Version returns a version of a bot platform adapter. It is used for debugging purposes.
	Version() string
}

BotPlatform describes current bot platform

type BotProfile added in v0.18.0

type BotProfile interface {
	ID() string
	Router() Router
	DefaultLocale() i18n.Locale
	SupportedLocales() []i18n.Locale
	NewBotChatData() botsfwmodels.BotChatData
	NewPlatformUserData() botsfwmodels.PlatformUserData
	GetTranslations() BotTranslations
}

func NewBotProfile added in v0.18.0

func NewBotProfile(
	id string,
	router Router,
	newBotChatData func() botsfwmodels.BotChatData,
	newBotUserData func() botsfwmodels.PlatformUserData,
	defaultLocale i18n.Locale,
	supportedLocales []i18n.Locale,
	translations BotTranslations,
	options ...BotProfileOption,
) BotProfile

type BotProfileOption added in v0.77.3

type BotProfileOption func(*botProfileConfig)

func WithPublishedCommandOrder added in v0.77.3

func WithPublishedCommandOrder(
	order BotCommandOrder,
	pinnedCommands ...string,
) BotProfileOption

WithPublishedCommandOrder configures how a profile exposes its published commands. Pinned command codes are required to occur exactly once.

type BotRecordsFieldsSetter added in v0.16.0

type BotRecordsFieldsSetter interface {

	// Platform returns platform name, e.g. 'telegram', 'fbmessenger', etc.
	// This method is for debug pruposes and to indicate that different platforms may have different fields
	// Though '*' can be used for a generic setter that works for all platforms
	// If both '*' and platform specific setters are defined, the generic setter will be used first.
	Platform() string

	// SetBotUserFields sets fields of bot user record
	SetBotUserFields(botUser botsfwmodels.PlatformUserData, sender botinput.Sender, botID, botUserID, appUserID string) error

	// SetBotChatFields sets fields of bot botChat record
	// TODO: document isAccessGranted parameter
	SetBotChatFields(botChat botsfwmodels.BotChatData, chat botinput.Chat, botID, botUserID, appUserID string, isAccessGranted bool) error
}

type BotSettings

type BotSettings struct {

	// Platform is a platform that bot is running on
	// E.g.: Telegram, Viber, Facebook Messenger, WhatsApp, etc.
	Platform botsfwconst.Platform

	// Env is an environment where bot is running
	// E.g.: Production/Live, Local/Dev, Staging, etc.
	Env string

	// Profile is a bot profile that defines bot's behavior
	// It includes commands router and some other settings
	// More in BotProfile documentation.
	Profile BotProfile

	// Code is a human-readable ID of a bot.
	// When displayed it is usually prefixed with @.
	// For example:
	//   - @listus_bot for https://t.me/listus_bot
	Code string

	// ID is a bot-platform ID of a bot. For example, it could be a GUID.
	// Not all platforms use it. For example Telegram doesn't use it.
	ID string

	// Token is used to authenticate bot with a platform when it is not responding to a webhook
	// but calling platform APIs directly.
	Token string

	// PaymentToken is used to process payments on bot platform
	PaymentToken string

	// PaymentTestToken is used to process test payments on bot platform
	PaymentTestToken string

	// VerifyToken is used by Facebook Messenger - TODO: Document how it is used and add a link to Facebook docs
	VerifyToken string

	// GAToken is Google Analytics token - TODO: Refactor tu support multiple or move out
	GAToken string

	// WebhookSecretToken is the secret Telegram (or other platform) sends back on every
	// webhook call in the `X-Telegram-Bot-Api-Secret-Token` header (set via `secret_token`
	// when registering the webhook, e.g. Telegram's `setWebhook`). Webhook handlers MUST
	// verify this value (constant-time) before processing an update, otherwise anyone who
	// knows the bot's webhook URL can POST forged updates and impersonate any platform user.
	//
	// If left empty, no verification is possible for this bot - this is a backward-compat
	// escape hatch for existing deployments, not a recommended posture. See
	// RequireWebhookSecret to make an empty secret a hard failure instead.
	WebhookSecretToken string

	// RequireWebhookSecret, when true, tells a webhook handler to reject all requests for
	// this bot (rather than just logging a warning) if WebhookSecretToken is empty. Defaults
	// to false (off) so existing deployments that haven't configured a secret yet keep
	// working, but every bot SHOULD set WebhookSecretToken and flip this to true.
	RequireWebhookSecret bool

	// Locale is a default locale for a bot.
	// While a bot profile can support multiple locales a bot can be dedicated to a specific country/language
	Locale i18n.Locale

	// Store owns framework identity and chat state for this bot. It is a narrow
	// use-case port, never a generic database handle.
	Store botsfwstore.StateStore

	// UserErrorDetails controls whether technical command-processing errors are
	// available to the user. The zero value preserves the legacy presentation.
	//
	// This is deliberately a per-bot opt-in. A host that accepts the disclosure
	// risk can select an expandable, same-message presentation without changing
	// the policy of every bot served by the same framework process.
	UserErrorDetails UserErrorDetailsPolicy
}

BotSettings keeps parameters of a bot that are static and are not changed in runtime

func NewBotSettings

func NewBotSettings(
	platform botsfwconst.Platform,
	environment string,
	profile BotProfile,
	code, id, token, gaToken string,
	locale i18n.Locale,
	store botsfwstore.StateStore,
) BotSettings

NewBotSettings configures bot application

func NewBotSettingsWithContext added in v0.76.1

func NewBotSettingsWithContext(
	ctx context.Context,
	platform botsfwconst.Platform,
	environment string,
	profile BotProfile,
	code, id, token, gaToken string,
	locale i18n.Locale,
	store botsfwstore.StateStore,
) BotSettings

NewBotSettingsWithContext configures a bot application using the environment provider attached to ctx for optional token fallbacks.

type BotSettingsBy added in v0.35.0

type BotSettingsBy struct {

	// ByCode keeps settings by bot code - it is a human-readable ID of a bot.
	//
	// Deprecated: ambiguous once more than one platform is in play, because the
	// same code may legitimately be used for the same product on Telegram and on
	// WhatsApp. First registration wins here. Use ByPlatformAndCode, or resolve
	// via BotContextProvider.GetBotContext which is platform-scoped.
	ByCode map[string]*BotSettings

	// ByID keeps settings by bot ID - it is a machine-readable ID of a bot.
	//
	// Deprecated: ambiguous across platforms, as ByCode. Use ByPlatformAndID.
	ByID map[string]*BotSettings

	ByProfile map[string][]*BotSettings

	// ByPlatformAndCode keeps settings by platform, then bot code.
	//
	// Bot codes are only unique WITHIN a platform: "debtus" on Telegram and
	// "debtus" on WhatsApp are different bots with different tokens.
	ByPlatformAndCode map[botsfwconst.Platform]map[string]*BotSettings

	// ByPlatformAndID keeps settings by platform, then bot ID.
	ByPlatformAndID map[botsfwconst.Platform]map[string]*BotSettings
}

SettingsBy keeps settings per different keys (ID, code, API token, Locale) TODO: Decide if it should have map[string]*BotSettings instead of map[string]BotSettings

func NewBotSettingsBy

func NewBotSettingsBy(bots ...BotSettings) (settingsBy BotSettingsBy)

NewBotSettingsBy create settings per different keys (ID, code, API token, Locale)

Bot codes and IDs must be unique WITHIN a platform, not globally. The same product on two platforms legitimately shares a code — "debtus" on Telegram and "debtus" on WhatsApp are different bots with different tokens — and rejecting that made a second platform impossible to register.

type BotSettingsProvider added in v0.35.0

type BotSettingsProvider func(ctx context.Context) BotSettingsBy

SettingsProvider returns settings per different keys (ID, code, API token, Locale)

type BotState

type BotState interface {
	IsNewerThen(chatEntity botsfwmodels.BotChatData) bool
}

BotState provides state of the bot. Deprecated: use WebhookUserData.IsNewerThen instead.

type BotTranslations added in v0.62.0

type BotTranslations struct {
	Description      string
	ShortDescription string
	Commands         []BotCommand
}

type BotUserCreator added in v0.18.0

type BotUserCreator func(c context.Context, botID string, apiUser botinput.Actor) (botsfwmodels.PlatformUserData, error)

type CallbackAction

type CallbackAction func(whc WebhookContext, callbackUrl *url.URL) (m botmsg.MessageFromBot, err error)

CallbackAction defines a callback action bot can perform in response to a callback command

type CallbackQueryAcknowledger added in v0.77.4

type CallbackQueryAcknowledger interface {
	AcknowledgeCallbackQuery(text string, showAlert bool) error
	WasCallbackQueryAcknowledged() bool
}

CallbackQueryAcknowledger is implemented by platform webhook contexts that can dismiss a callback-query loading indicator immediately.

type CapabilityID added in v0.77.1

type CapabilityID string

type ChosenInlineResultAction added in v0.53.1

type ChosenInlineResultAction func(whc WebhookContext, chosenResult botinput.ChosenInlineResult, queryUrl *url.URL) (m botmsg.MessageFromBot, err error)

type ChosenInlineResultHandlerFunc added in v0.51.0

type ChosenInlineResultHandlerFunc func(whc WebhookContext, inlineQuery botinput.ChosenInlineResult) (handled bool, m botsfw2.MessageFromBot, err error)

ChosenInlineResultHandlerFunc defines a function that handles chosen inline result

type Command

type Command struct {
	Code       CommandCode
	InputTypes []botinput.Type // Instant match if != TypeUnknown && == whc.InputTypes()
	Icon       string
	Replies    []Command
	Title      string
	Titles     map[string]string
	ExactMatch string
	Commands   []string
	Matcher    CommandMatcher
	//
	Action                   CommandAction
	TextAction               TextAction
	StartAction              StartAction
	CallbackAction           CallbackAction
	LocationAction           LocationAction
	InlineQueryAction        InlineQueryAction
	ChosenInlineResultAction ChosenInlineResultAction
	PreCheckoutQueryAction   PreCheckoutQueryAction
	SuccessfulPaymentAction  SuccessfulPaymentAction
	RefundedPaymentAction
}

Command defines command metadata and action

func NewCallbackCommand

func NewCallbackCommand(code CommandCode, action CallbackAction) Command

NewCallbackCommand create a definition of a callback command

func NewInlineQueryCommand

func NewInlineQueryCommand(code CommandCode, action CommandAction) Command

func (Command) DefaultTitle

func (c Command) DefaultTitle(whc WebhookContext) string

DefaultTitle returns a default title for a command in current Locale

func (Command) String

func (c Command) String() string

func (Command) TitleByKey

func (c Command) TitleByKey(key string, whc WebhookContext) string

TitleByKey returns a short/long title for a command in current Locale

type CommandAction

type CommandAction func(whc WebhookContext) (m botmsg.MessageFromBot, err error)

CommandAction defines an action bot can perform in response to a command

type CommandCode added in v0.45.0

type CommandCode string
const (
	ReservedCancelCommand CommandCode = "cancel"
	ReservedHomeCommand   CommandCode = "home"
)

type CommandMatcher

type CommandMatcher func(command Command, whc WebhookContext) bool

CommandMatcher returns true if action is matched to user input

type CommandOwnership added in v0.77.1

type CommandOwnership struct {
	Code               CommandCode
	Aliases            []CommandCode
	CallbackNamespaces []string
	InputTypes         []botinput.Type
}

CommandOwnership declares a command code claimed by a feature for one or more input types. It is metadata only: registration remains compatible with existing Router.RegisterCommands callers.

type CommandResponseResponder added in v0.77.1

type CommandResponseResponder interface {
	ResponderForCommand(CommandCode) WebhookResponder
}

CommandResponseResponder is implemented by host-composed responders that select presentation authority from the router's matched command, rather than from data supplied by a feature message.

type CreateWebhookContextArgs added in v0.18.0

type CreateWebhookContextArgs struct {
	HttpRequest  *http.Request // TODO: Can we get rid of it? Needed for botHost.GetHTTPClient()
	AppContext   AppContext
	BotContext   BotContext
	WebhookInput botinput.InputMessage
	Store        botsfwstore.StateStore
}

func NewCreateWebhookContextArgs added in v0.18.0

func NewCreateWebhookContextArgs(
	httpRequest *http.Request,
	appContext AppContext,
	botContext BotContext,
	webhookInput botinput.InputMessage,
	store botsfwstore.StateStore,
) CreateWebhookContextArgs

type EnvProvider added in v0.76.1

type EnvProvider interface {
	LookupEnv(name string) (value string, ok bool)
}

EnvProvider resolves immutable runtime configuration by name. Implementations must be safe for concurrent use when the same provider is shared by concurrent request contexts.

func EnvProviderFromContext added in v0.76.1

func EnvProviderFromContext(ctx context.Context) EnvProvider

EnvProviderFromContext returns the context provider, or the process environment provider when no override was attached.

type EnvProviderFunc added in v0.76.1

type EnvProviderFunc func(name string) (value string, ok bool)

EnvProviderFunc adapts a function to EnvProvider.

func (EnvProviderFunc) LookupEnv added in v0.76.1

func (f EnvProviderFunc) LookupEnv(name string) (value string, ok bool)

LookupEnv implements EnvProvider.

type ErrAuthFailed

type ErrAuthFailed string

ErrAuthFailed raised if authentication failed

func (ErrAuthFailed) Error

func (e ErrAuthFailed) Error() string

type ExecutionContext added in v0.25.0

type ExecutionContext interface {
	Context() context.Context
}

ExecutionContext wraps Context() and adds no independent value. Deprecated: use WebhookRequestContext directly.

type FeatureMount added in v0.77.1

type FeatureMount struct {
	ID           string
	Mode         FeatureMountMode
	Namespace    string
	Navigator    NavigatorID
	Capabilities []CapabilityID
	Commands     []CommandOwnership
}

FeatureMount is the stable host-to-feature integration contract. Navigator and Capabilities are intentionally strings so individual bot applications can evolve independently while hosts can validate and discover their surfaces.

type FeatureMountMode added in v0.77.1

type FeatureMountMode string

FeatureMountMode describes how a feature is exposed by its host bot. Dedicated features own the bot surface; embedded features share it with the host and therefore must use an unambiguous namespace and command ownership.

const (
	FeatureMountDedicated FeatureMountMode = "dedicated"
	FeatureMountEmbedded  FeatureMountMode = "embedded"
)

type FeatureRegistry added in v0.77.1

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

FeatureRegistry is the host startup registry. Its constructor validates mounted features before a router can be exposed, while old hosts may adopt it without changing BotProfile or Router APIs.

func NewFeatureRegistry added in v0.77.1

func NewFeatureRegistry(mounts ...FeatureMount) (*FeatureRegistry, error)

func (*FeatureRegistry) Mounts added in v0.77.1

func (r *FeatureRegistry) Mounts() []FeatureMount

type FeatureScenario added in v0.77.1

type FeatureScenario struct {
	Mount       FeatureMount
	Messages    []ScenarioMessage
	Navigation  []NavigatorID
	SideEffects []string
}

FeatureScenario is an executed, deterministic host-level acceptance trace. It records both router-return and direct-send paths so presentation policy cannot be bypassed by choosing a different response path.

func ReplayFeatureScenario added in v0.77.1

func ReplayFeatureScenario(mount FeatureMount, policy PresentationPolicy, flow FeatureScenarioFlow) (FeatureScenario, error)

ReplayFeatureScenario validates a mount and executes the supplied flow under that mount context. It is intentionally transport-free, but exercises the same router-return and direct-send ownership boundaries as a host adapter.

type FeatureScenarioContext added in v0.77.1

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

FeatureScenarioContext provides the only output paths a replay fixture may use. SendHost models host UI (Home, keyboard removal, or inline controls), while feature paths are always treated as non-host-owned.

func (*FeatureScenarioContext) Navigate added in v0.77.1

func (c *FeatureScenarioContext) Navigate(to NavigatorID)

func (*FeatureScenarioContext) ReturnFromRouter added in v0.77.1

func (c *FeatureScenarioContext) ReturnFromRouter(message botmsg.MessageFromBot) error

func (*FeatureScenarioContext) SendDirect added in v0.77.1

func (c *FeatureScenarioContext) SendDirect(message botmsg.MessageFromBot) error

func (*FeatureScenarioContext) SendHost added in v0.77.1

func (c *FeatureScenarioContext) SendHost(message botmsg.MessageFromBot) error

func (*FeatureScenarioContext) SideEffect added in v0.77.1

func (c *FeatureScenarioContext) SideEffect(effect string)

type FeatureScenarioExpectation added in v0.77.1

type FeatureScenarioExpectation struct {
	Mode        FeatureMountMode
	Messages    int
	Paths       []ScenarioMessagePath
	Navigation  []NavigatorID
	SideEffects []string
	Policy      PresentationPolicy
}

type FeatureScenarioFlow added in v0.77.1

type FeatureScenarioFlow func(*FeatureScenarioContext) error

FeatureScenarioFlow is supplied by a feature adapter fixture. The harness executes it under a concrete mount and validates every emitted message.

type HttpRouter added in v0.11.0

type HttpRouter interface {
	Handle(method string, path string, handle http.HandlerFunc)
}

type InlineInputHandler added in v0.51.0

type InlineInputHandler struct {
	ProfileID                string // Not sure if we really need it
	HandleInlineQuery        InlineQueryHandlerFunc
	HandleChosenInlineResult ChosenInlineResultHandlerFunc
}

InlineInputHandler defines handlers to deal with inline inputs

type InlineQueryAction added in v0.53.1

type InlineQueryAction func(whc WebhookContext, inlineQuery botinput.InlineQuery, queryUrl *url.URL) (m botmsg.MessageFromBot, err error)

type InlineQueryHandlerFunc added in v0.50.2

type InlineQueryHandlerFunc func(whc WebhookContext, inlineQuery botinput.InlineQuery) (handled bool, m botsfw2.MessageFromBot, err error)

InlineQueryHandlerFunc defines a function that handles inline query

type InputMessage

type InputMessage interface {
	Text() string
}

InputMessage represents single input message

type LocationAction added in v0.70.2

type LocationAction func(whc WebhookContext, latitude, longitude float64) (m botmsg.MessageFromBot, err error)

type MessengerResponse

type MessengerResponse interface {
	GetMessageID() string
}

MessengerResponse represents response from a messenger

type NavigatorID string

type OnMessageSentResponse

type OnMessageSentResponse struct {
	StatusCode int
	Message    MessengerResponse // TODO: change to some interface
}

OnMessageSentResponse represents response on message sent event

func SendMessageThroughGate added in v0.72.0

SendMessageThroughGate consults responder's SendGate, if any, and sends only if the send is permitted.

This is the single seam every outbound send should route through, so a platform gets one place to refuse rather than one per call site. On refusal it returns a zero response and the refusal error, having attempted no send.

type PersistentBottomKeyboardPolicy added in v0.77.1

type PersistentBottomKeyboardPolicy string
const (
	PersistentBottomKeyboardAllow    PersistentBottomKeyboardPolicy = "allow"
	PersistentBottomKeyboardDeny     PersistentBottomKeyboardPolicy = "deny"
	PersistentBottomKeyboardHostOnly PersistentBottomKeyboardPolicy = "host-only"
)

type PreCheckoutQueryAction added in v0.62.0

type PreCheckoutQueryAction func(whc WebhookContext, preCheckout botinput.PreCheckoutQuery) (m botmsg.MessageFromBot, err error)

type PresentationPolicy added in v0.77.1

type PresentationPolicy struct {
	PersistentBottomKeyboard PersistentBottomKeyboardPolicy
}

PresentationPolicy is supplied by the bot host and is applied before every responder send when the responder is wrapped with NewPolicyResponder.

func (PresentationPolicy) Validate added in v0.77.1

func (p PresentationPolicy) Validate(m botmsg.MessageFromBot, hostOwned bool) error

type RefundedPaymentAction added in v0.62.0

type RefundedPaymentAction func(whc WebhookContext, payment botinput.RefundedPayment) (m botmsg.MessageFromBot, err error)

type Router added in v0.49.0

type Router interface {
	RegisterCommands(commands ...Command)
	RegisterCommandsForInputType(inputType botinput.Type, commands ...Command)

	// Dispatch requests to commands by input type, command code or a matching function
	Dispatch(webhookHandler WebhookHandler, responder WebhookResponder, whc WebhookContext) error

	// RegisteredCommands returns all registered commands
	RegisteredCommands() map[botinput.Type]map[CommandCode]Command

	// SetFallbackHandler registers a catch-all action for the given input type.
	// The fallback fires only when no registered command matches the input.
	// Unlike a catch-all Matcher command, the fallback is order-independent:
	// it is stored separately and never blocks the normal command-matching loop.
	// Only one fallback per input type is supported; a second call replaces the first.
	SetFallbackHandler(inputType botinput.Type, action CommandAction)
}

Router dispatches requests to commands by input type, command code or a matching function

type RouterResponderProvider added in v0.77.1

type RouterResponderProvider interface {
	GetRouterResponder(WebhookContext, WebhookResponder) WebhookResponder
}

RouterResponderProvider is an optional host adapter seam. It lets an adapter supply a router-only responder while WebhookContext retains the feature responder used for direct sends.

type ScenarioMessage added in v0.77.1

type ScenarioMessage struct {
	Path    ScenarioMessagePath
	Message botmsg.MessageFromBot
}

type ScenarioMessagePath added in v0.77.1

type ScenarioMessagePath string

ScenarioMessagePath identifies the transport path used to present a message. Feature-returned messages and direct sends are feature-owned; HostSend is available only to the host fixture for its own UI.

const (
	ScenarioRouterReturn ScenarioMessagePath = "router-return"
	ScenarioDirectSend   ScenarioMessagePath = "direct-send"
	ScenarioHostSend     ScenarioMessagePath = "host-send"
)

type SendGate added in v0.72.0

type SendGate interface {
	// CanSend reports whether m may be sent right now.
	//
	// A nil error means the send may proceed. A non-nil error means it may not,
	// and describes why; implementations should wrap ErrSendNotPermitted so the
	// refusal is classifiable.
	//
	// CanSend must not perform the send, and should avoid network calls: it is
	// consulted on every outbound message.
	CanSend(c context.Context, m botmsg.MessageFromBot) error
}

SendGate is an optional interface a WebhookResponder may implement to refuse sends its platform does not currently permit.

It exists because "a bot may message any chat it knows, at any time" is a Telegram property, not a universal one. Telegram's responder therefore does not implement SendGate, and nothing about its behaviour changes.

Other platforms gate sending. WhatsApp permits free-form messages only within 24 hours of the recipient's last reply; outside that window a send fails, and only a pre-approved template may be delivered. Without this seam a platform has no way to say "not now" — the router would send unconditionally, spending an API call to earn a rejection, or worse, delivering a billable template message the app never intended.

A responder that does not implement SendGate is treated as always permitting, so this is additive: existing responders keep working untouched.

type StartAction added in v0.64.0

type StartAction TextAction

type SuccessfulPaymentAction added in v0.62.0

type SuccessfulPaymentAction func(whc WebhookContext, payment botinput.SuccessfulPayment) (m botmsg.MessageFromBot, err error)

type TextAction added in v0.54.0

type TextAction func(whc WebhookContext, text string) (m botmsg.MessageFromBot, err error)

type TranslatorProvider

type TranslatorProvider func(c context.Context) i18n.Translator

TranslatorProvider translates texts

type UserErrorDetailsDisclosure added in v0.77.7

type UserErrorDetailsDisclosure string

UserErrorDetailsDisclosure describes how technical error details are exposed to a bot user.

const (
	// UserErrorDetailsDisclosureLegacy preserves the existing error message.
	UserErrorDetailsDisclosureLegacy UserErrorDetailsDisclosure = ""

	// UserErrorDetailsDisclosureExpandable adds technical details to the same
	// message in an expandable blockquote on Telegram. It avoids callback state,
	// a second message, and Telegram's 64-byte callback-data limit.
	UserErrorDetailsDisclosureExpandable UserErrorDetailsDisclosure = "expandable"
)

type UserErrorDetailsPolicy added in v0.77.7

type UserErrorDetailsPolicy struct {
	Disclosure UserErrorDetailsDisclosure
}

UserErrorDetailsPolicy is an explicit host-level disclosure decision.

type WebhookAnalytics added in v0.57.0

type WebhookAnalytics interface {
	Enqueue(message analytics.Message)
}

type WebhookContext

WebhookContext is the full request context passed to every command action handler. It is a composition of focused sub-interfaces. Prefer accepting the narrowest sub-interface that covers your function's actual needs.

type WebhookContextBase

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

WebhookContextBase provides base implementation of WebhookContext interface TODO: Document purpose of a dedicated base struct (e.g. example of usage by developers)

func NewWebhookContextBase

func NewWebhookContextBase(
	args CreateWebhookContextArgs,
	botPlatform BotPlatform,
	recordsFieldsSetter BotRecordsFieldsSetter,
	getIsInGroup func() (bool, error),
	getLocaleAndChatID func(c context.Context) (locale, chatID string, err error),
) (whcb *WebhookContextBase, err error)

NewWebhookContextBase creates base bot context

func (*WebhookContextBase) Analytics added in v0.57.0

func (whcb *WebhookContextBase) Analytics() WebhookAnalytics

func (*WebhookContextBase) AppContext added in v0.35.0

func (whcb *WebhookContextBase) AppContext() AppContext

AppContext returns bot app context

func (*WebhookContextBase) AppUserData added in v0.29.0

func (whcb *WebhookContextBase) AppUserData() (appUserData botsfwmodels.AppUserData, err error)

func (*WebhookContextBase) AppUserEntity

func (whcb *WebhookContextBase) AppUserEntity() botsfwmodels.AppUserData

AppUserEntity current app user entity from data storage

func (*WebhookContextBase) AppUserID added in v0.13.0

func (whcb *WebhookContextBase) AppUserID() string

AppUserID returns the application user linked to the current bot identity.

func (*WebhookContextBase) BotChatID

func (whcb *WebhookContextBase) BotChatID() (botChatID string, err error)

BotChatID returns bot botChat ID

func (*WebhookContextBase) BotContext

func (whcb *WebhookContextBase) BotContext() BotContext

func (*WebhookContextBase) BotPlatform

func (whcb *WebhookContextBase) BotPlatform() BotPlatform

BotPlatform indicates on which bot platform we process message

func (*WebhookContextBase) Chat

func (whcb *WebhookContextBase) Chat() botinput.Chat

Chat returns webhook botChat

func (*WebhookContextBase) ChatData added in v0.16.2

func (whcb *WebhookContextBase) ChatData() botsfwmodels.BotChatData

ChatData returns current bot chat state, creating and linking the identity through the injected store when the platform supplied a chat ID.

func (*WebhookContextBase) CommandText

func (whcb *WebhookContextBase) CommandText(title, icon string) string

CommandText returns a title for a command

func (*WebhookContextBase) Context

func (whcb *WebhookContextBase) Context() context.Context

Context for current request

func (*WebhookContextBase) Environment

func (whcb *WebhookContextBase) Environment() string

Environment defines current environment (PROD, DEV, LOCAL, etc)

func (*WebhookContextBase) ExecutionContext

func (whcb *WebhookContextBase) ExecutionContext() ExecutionContext

ExecutionContext returns an execution context for strongo app

func (*WebhookContextBase) GetAppUser

func (whcb *WebhookContextBase) GetAppUser() (botsfwmodels.AppUserData, error)

GetAppUser loads information about the current app user through the state-store port.

func (*WebhookContextBase) GetBotCode

func (whcb *WebhookContextBase) GetBotCode() string

GetBotCode returns current bot code

func (*WebhookContextBase) GetBotSettings

func (whcb *WebhookContextBase) GetBotSettings() *BotSettings

GetBotSettings settings of the current bot

func (*WebhookContextBase) GetBotToken

func (whcb *WebhookContextBase) GetBotToken() string

GetBotToken returns current bot API token

func (*WebhookContextBase) GetBotUser added in v0.56.0

func (whcb *WebhookContextBase) GetBotUser() (botsfwstore.PlatformUser, error)

func (*WebhookContextBase) GetBotUserID added in v0.16.2

func (whcb *WebhookContextBase) GetBotUserID() string

func (*WebhookContextBase) GetRecipient

func (whcb *WebhookContextBase) GetRecipient() botinput.Recipient

GetRecipient returns receiver of the message

func (*WebhookContextBase) GetTime

func (whcb *WebhookContextBase) GetTime() time.Time

GetTime returns time of the message

func (*WebhookContextBase) GetTranslator added in v0.61.0

func (whcb *WebhookContextBase) GetTranslator(locale string) i18n.SingleLocaleTranslator

func (*WebhookContextBase) HasChatData added in v0.16.2

func (whcb *WebhookContextBase) HasChatData() bool

HasChatData return true if messages is within botChat

func (*WebhookContextBase) Input

Input returns webhook input

func (*WebhookContextBase) InputType

func (whcb *WebhookContextBase) InputType() botinput.Type

InputType returns input type

func (*WebhookContextBase) IsInGroup

func (whcb *WebhookContextBase) IsInGroup() (bool, error)

IsInGroup signals if the bot request is send within group botChat

func (*WebhookContextBase) Locale

func (whcb *WebhookContextBase) Locale() i18n.Locale

Locale indicates current language

func (*WebhookContextBase) LogRequest

func (whcb *WebhookContextBase) LogRequest()

LogRequest logs request data to logging system

func (*WebhookContextBase) MessageText

func (whcb *WebhookContextBase) MessageText() string

MessageText returns text of a received message

func (*WebhookContextBase) MustBotChatID

func (whcb *WebhookContextBase) MustBotChatID() (chatID string)

MustBotChatID returns bot botChat ID and panic if missing it

func (*WebhookContextBase) NewMessage

func (whcb *WebhookContextBase) NewMessage(text string) (m botsfw3.MessageFromBot)

NewMessage creates a new text message from bot

func (*WebhookContextBase) NewMessageByCode

func (whcb *WebhookContextBase) NewMessageByCode(messageCode string, a ...interface{}) (m botsfw3.MessageFromBot)

NewMessageByCode creates new translated message by i18n code

func (*WebhookContextBase) RecordsFieldsSetter added in v0.16.2

func (whcb *WebhookContextBase) RecordsFieldsSetter() BotRecordsFieldsSetter

func (*WebhookContextBase) Request

func (whcb *WebhookContextBase) Request() *http.Request

Request returns reference to current HTTP request

func (*WebhookContextBase) SaveBotChat added in v0.18.0

func (whcb *WebhookContextBase) SaveBotChat() error

func (*WebhookContextBase) SetBotUserAccessGranted added in v0.76.0

func (whcb *WebhookContextBase) SetBotUserAccessGranted(value bool) error

func (*WebhookContextBase) SetChatID

func (whcb *WebhookContextBase) SetChatID(chatID string)

SetChatID sets botChat ID - TODO: Should it be private?

func (*WebhookContextBase) SetContext

func (whcb *WebhookContextBase) SetContext(c context.Context)

SetContext sets current context // TODO: explain why we need this as probably should be in constructor?

func (*WebhookContextBase) SetLocale

func (whcb *WebhookContextBase) SetLocale(code5 string) error

SetLocale sets current language

func (*WebhookContextBase) SetUser added in v0.70.6

func (whcb *WebhookContextBase) SetUser(id string, data botsfwmodels.AppUserData)

func (WebhookContextBase) Translate

func (t WebhookContextBase) Translate(key string, args ...interface{}) string

Translate translates string

func (WebhookContextBase) TranslateNoWarning

func (t WebhookContextBase) TranslateNoWarning(key string, args ...interface{}) string

TranslateNoWarning translates string without warnings

func (WebhookContextBase) TranslateWithMap added in v0.58.0

func (t WebhookContextBase) TranslateWithMap(key string, args map[string]string) string

type WebhookDriver

type WebhookDriver interface {
	RegisterWebhookHandlers(httpRouter HttpRouter, pathPrefix string, webhookHandlers ...WebhookHandler)
	HandleWebhook(w http.ResponseWriter, r *http.Request, webhookHandler WebhookHandler)
}

WebhookDriver is doing initial request & final response processing. That includes logging, creating input messages in a general format, sending response.

type WebhookHandler

type WebhookHandler interface {

	// RegisterHttpHandlers registers HTTP handlers for bot API
	RegisterHttpHandlers(driver WebhookDriver, botHost BotHost, router HttpRouter, pathPrefix string)

	// HandleWebhookRequest handles incoming webhook request
	HandleWebhookRequest(w http.ResponseWriter, r *http.Request)

	// GetBotContextAndInputs returns bot context and inputs for current request
	// It returns multiple inputs as some platforms (like Facebook Messenger)
	// may send multiple message in one request
	GetBotContextAndInputs(c context.Context, r *http.Request) (botContext *BotContext, entriesWithInputs []botinput.EntryInputs, err error)

	// CreateWebhookContext creates WebhookContext for current webhook request
	CreateWebhookContext(args CreateWebhookContextArgs) (WebhookContext, error)

	GetResponder(w http.ResponseWriter, whc WebhookContext) WebhookResponder
	HandleUnmatched(whc WebhookContext) (m botsfw2.MessageFromBot)
}

WebhookHandler handles requests from a specific bot API This is implemented by different botsfw packages, e.g. https://github.com/bots-go-framework/bots-fw-telegram TODO: Simplify interface by decomposing it into smaller interfaces? Probably next method could/should be decoupled: CreateBotCoreStores()

type WebhookHandlerBase added in v0.16.0

type WebhookHandlerBase struct {
	WebhookDriver
	BotHost
	BotPlatform
	//RecordsMaker        botsfwmodels.BotRecordsMaker
	RecordsFieldsSetter BotRecordsFieldsSetter
	TranslatorProvider  TranslatorProvider
}

WebhookHandlerBase provides base implementation for a bot handler

func (*WebhookHandlerBase) Register added in v0.16.0

func (bh *WebhookHandlerBase) Register(d WebhookDriver, h BotHost)

Register driver

type WebhookI18n added in v0.71.36

type WebhookI18n interface {
	i18n.SingleLocaleTranslator

	// SetLocale switches the active locale for this request.
	SetLocale(code5 string) error

	// GetTranslator returns a translator pinned to the given locale code.
	GetTranslator(locale string) i18n.SingleLocaleTranslator

	// CommandText formats a command title and icon into a display string.
	CommandText(title, icon string) string
}

WebhookI18n provides localisation support for the current request.

type WebhookInlineQueryContext

type WebhookInlineQueryContext interface {
}

WebhookInlineQueryContext provides context for inline query Deprecated: not used; will be removed in a future version.

type WebhookInputContext added in v0.71.36

type WebhookInputContext interface {
	BotInputProvider

	// GetBotUserID returns the platform-specific user ID of the sender as a string.
	GetBotUserID() string

	// MustBotChatID returns the chat ID or panics if it cannot be determined.
	MustBotChatID() string

	// IsInGroup reports whether the message was received in a group chat.
	IsInGroup() (bool, error)
}

WebhookInputContext provides access to the incoming message from the user.

type WebhookMessaging added in v0.71.36

type WebhookMessaging interface {
	// NewMessage creates a plain-text MessageFromBot.
	NewMessage(text string) botmsg.MessageFromBot

	// NewMessageByCode creates a MessageFromBot from an i18n key, formatting it with args.
	NewMessageByCode(messageCode string, a ...interface{}) botmsg.MessageFromBot

	// NewEditMessage creates a MessageFromBot that edits the previously sent message.
	NewEditMessage(text string, format botmsg.Format) (botmsg.MessageFromBot, error)

	// Responder returns the WebhookResponder used to deliver messages to the platform.
	Responder() WebhookResponder
}

WebhookMessaging provides helpers to construct and send messages back to the user.

type WebhookNewContext

type WebhookNewContext struct {
	BotContext
	botinput.InputMessage
}

WebhookNewContext TODO: needs to be checked & described

type WebhookRequestContext added in v0.71.36

type WebhookRequestContext interface {
	// Context returns the Go context for this request.
	Context() context.Context

	// SetContext replaces the request context (e.g. after adding values or a deadline).
	SetContext(c context.Context)

	// Request returns the raw HTTP request.
	Request() *http.Request

	// Environment returns the deployment environment (e.g. "local", "production").
	Environment() string

	// BotPlatform returns the platform this request arrived on (Telegram, Viber, FBM, …).
	BotPlatform() BotPlatform

	// BotContext returns settings and host information for the current bot.
	BotContext() BotContext

	// GetBotCode is a convenience shortcut for BotContext().BotSettings.Code.
	GetBotCode() string

	// GetBotSettings is a convenience shortcut for BotContext().BotSettings.
	GetBotSettings() *BotSettings

	// AppContext returns application-level presentation context (for example i18n).
	AppContext() AppContext

	// ExecutionContext returns the execution context.
	// Deprecated: use Context() directly.
	ExecutionContext() ExecutionContext
}

WebhookRequestContext provides identity and infrastructure access for the current request.

type WebhookResponder

type WebhookResponder interface {
	SendMessage(c context.Context, m botmsg.MessageFromBot, channel botmsg.BotAPISendMessageChannel) (response OnMessageSentResponse, err error)
	DeleteMessage(c context.Context, messageID string) (err error)
}

WebhookResponder is an API provider to send messages through a messenger

func NewCommandPolicyResponder added in v0.77.1

func NewCommandPolicyResponder(next WebhookResponder, policy PresentationPolicy, hostCommands ...CommandCode) WebhookResponder

NewCommandPolicyResponder makes router-return ownership depend on the command codes selected by host composition. Direct sends retain feature ownership.

func NewHostPolicyResponder added in v0.77.1

func NewHostPolicyResponder(next WebhookResponder, policy PresentationPolicy) WebhookResponder

func NewPolicyResponder added in v0.77.1

func NewPolicyResponder(next WebhookResponder, policy PresentationPolicy) WebhookResponder

NewPolicyResponder wraps both router-returned and direct responder sends, provided the host installs the wrapper in the WebhookContext and router. NewPolicyResponder creates a feature-owned responder; it cannot send a host-only bottom keyboard. Hosts must use NewHostPolicyResponder explicitly.

func ResponseResponderForCommand added in v0.77.1

func ResponseResponderForCommand(responder WebhookResponder, code CommandCode) WebhookResponder

ResponseResponderForCommand is called by the router after it has selected a command. Only a host-composed responder can grant host presentation authority.

type WebhookTelemetry added in v0.71.36

type WebhookTelemetry interface {
	Analytics() WebhookAnalytics
}

WebhookTelemetry provides access to the analytics pipeline.

type WebhookUserData added in v0.71.36

type WebhookUserData interface {
	// ChatData returns the current bot chat's persistent data.
	// Returns nil for input types that have no associated chat (e.g. InlineQuery).
	ChatData() botsfwmodels.BotChatData

	// SaveBotChat persists the current chat data to the database.
	SaveBotChat() error

	// GetBotUser returns the current platform user without exposing a storage record.
	GetBotUser() (botUser botsfwstore.PlatformUser, err error)

	// SetBotUserAccessGranted changes the platform-user access flag through the
	// injected state-store port.
	SetBotUserAccessGranted(value bool) error

	// AppUserID returns the application-layer user ID linked to this bot user.
	AppUserID() string

	// SetUser caches the resolved app user ID and data into the context.
	SetUser(id string, data botsfwmodels.AppUserData)

	// AppUserData loads and returns the app user's persistent data.
	AppUserData() (botsfwmodels.AppUserData, error)

	// RecordsFieldsSetter returns the helper used to populate new bot/chat/user records.
	RecordsFieldsSetter() BotRecordsFieldsSetter

	// UpdateLastProcessed records the message sequence number / timestamp on the chat entity.
	UpdateLastProcessed(chatEntity botsfwmodels.BotChatData) error

	// IsNewerThen reports whether the current message is newer than the chat entity's
	// last-processed sequence number (used to detect and discard duplicate deliveries).
	IsNewerThen(chatEntity botsfwmodels.BotChatData) bool
}

WebhookUserData provides read/write access to the persistent state of the current bot user, app user, and chat.

Jump to

Keyboard shortcuts

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