ext

package
v2.0.0-rc.25 Latest Latest
Warning

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

Go to latest
Published: Feb 19, 2024 License: MIT Imports: 19 Imported by: 74

Documentation

Index

Constants

View Source
const DefaultMaxRoutines = 50

Variables

View Source
var (
	ErrPanicRecovered          = errors.New("panic recovered")
	ErrUnknownDispatcherAction = errors.New("unknown dispatcher action")
)
View Source
var (
	EndGroups      = errors.New("group iteration ended")
	ContinueGroups = errors.New("group iteration continued")
)
View Source
var (
	ErrMissingCertOrKeyFile = errors.New("missing certfile or keyfile")
	ErrExpectedEmptyServer  = errors.New("expected server to be nil")
	ErrNotFound             = errors.New("not found")
	ErrEmptyPath            = errors.New("empty path")
)
View Source
var ErrBotAlreadyExists = errors.New("bot already exists in bot mapping")
View Source
var ErrBotUrlPathAlreadyExists = errors.New("url path already exists in bot mapping")

Functions

func ValidateLoginQuery

func ValidateLoginQuery(query url.Values, token string) (bool, error)

ValidateLoginQuery validates a login widget query. See https://core.telegram.org/widgets/login#checking-authorization for more details.

func ValidateWebAppInitData

func ValidateWebAppInitData(initData string, token string) (bool, error)

ValidateWebAppInitData validates a webapp's initData field for safe use on the server-side. The initData field is stored as a query string, so this is converted and then validated. See https://core.telegram.org/bots/webapps#validating-data-received-via-the-web-app for more details.

func ValidateWebAppQuery

func ValidateWebAppQuery(query url.Values, token string) (bool, error)

ValidateWebAppQuery validates a webapp's initData query for safe use on the server side. The input is expected to be the parsed initData query string. See https://core.telegram.org/bots/webapps#validating-data-received-via-the-web-app for more details.

Types

type AddWebhookOpts

type AddWebhookOpts struct {
	// The secret token to be used to validate webhook authenticity.
	SecretToken string
}

AddWebhookOpts stores any optional parameters for the Updater.AddWebhook method.

type BaseProcessor

type BaseProcessor struct{}

BaseProcessor is the simplest version of the Processor; it simply calls the dispatcher straight away.

func (BaseProcessor) ProcessUpdate

func (bp BaseProcessor) ProcessUpdate(d *Dispatcher, b *gotgbot.Bot, ctx *Context) error

ProcessUpdate iterates over the list of groups to execute the matching handlers.

type Context

type Context struct {
	// gotgbot.Update is inlined so that we can access all fields immediately if necessary.
	*gotgbot.Update
	// Data represents update-local storage.
	// This can be used to pass data across handlers - for example, to cache operations relevant to the current update,
	// such as admin checks.
	Data map[string]interface{}

	// EffectiveMessage is the message which triggered the update, if available.
	// If the message is an InaccessibleMessage (eg, from a callbackquery), the message contents may be inaccessible.
	EffectiveMessage *gotgbot.Message
	// EffectiveChat is the chat the update was triggered in, if possible.
	EffectiveChat *gotgbot.Chat
	// EffectiveUser is the user who triggered the update, if possible.
	// Note: when adding a user, the user who ADDED should be the EffectiveUser;
	// they caused the update. If a user joins naturally, then they are the EffectiveUser.
	//
	// WARNING: It may be better to rely on EffectiveSender instead, which allows for easier use
	// in the case of linked channels, anonymous admins, or anonymous channels.
	EffectiveUser *gotgbot.User
	// EffectiveSender is the sender of the update. This can be either:
	//  - a user
	//  - an anonymous admin of the current chat, speaking through the chat
	//  - the linked channel of the current chat
	//  - an anonymous user, speaking through a channel
	EffectiveSender *gotgbot.Sender
}

TODO: extend to be used as a generic cancel context?

func NewContext

func NewContext(update *gotgbot.Update, data map[string]interface{}) *Context

NewContext populates a context with the relevant fields from the current update. It takes a data field in the case where custom data needs to be passed.

func (*Context) Args

func (c *Context) Args() []string

Args gets the list of whitespace-separated arguments of the message text.

type Dispatcher

type Dispatcher struct {
	// Processor defines how to process the raw updates being handled by the Dispatcher.
	// This can be extended to include additional error handling, metrics, etc.
	Processor Processor

	// Error handles any errors that are returned by matched handlers.
	// The return type determines how to proceed with the current group iteration.
	// The default action is DispatcherActionNoop, which will simply move to next group as expected.
	Error DispatcherErrorHandler
	// Panic handles any panics that occur during handler execution.
	// Panics from handlers are automatically recovered to ensure bot stability. Once recovered, this method is called
	// and is left to determine how to log or handle the errors.
	// If this field is nil, the error will be passed to UnhandledErrFunc.
	Panic DispatcherPanicHandler

	// UnhandledErrFunc provides more flexibility for dealing with unhandled update processing errors.
	// This includes errors when unmarshalling updates, unhandled panics during handler executions, or unknown
	// dispatcher actions.
	// If nil, the error goes to ErrorLog.
	UnhandledErrFunc ErrorFunc
	// ErrorLog specifies an optional logger for unexpected behavior from handlers.
	// If nil, logging is done via the log package's standard logger.
	ErrorLog *log.Logger
	// contains filtered or unexported fields
}

The Dispatcher struct is the default UpdateDispatcher implementation. It supports grouping of update handlers, allowing for powerful update handling flows. Customise the handling of updates by wrapping the Processor struct.

func NewDispatcher

func NewDispatcher(opts *DispatcherOpts) *Dispatcher

NewDispatcher creates a new Dispatcher, which process and handles incoming updates from the updates channel.

func (*Dispatcher) AddHandler

func (d *Dispatcher) AddHandler(handler Handler)

AddHandler adds a new handler to the dispatcher. The dispatcher will call CheckUpdate() to see whether the handler should be executed, and then HandleUpdate() to execute it.

func (*Dispatcher) AddHandlerToGroup

func (d *Dispatcher) AddHandlerToGroup(h Handler, group int)

AddHandlerToGroup adds a handler to a specific group; lowest number will be processed first.

func (*Dispatcher) CurrentUsage

func (d *Dispatcher) CurrentUsage() int

CurrentUsage returns the current number of concurrently processing updates.

func (*Dispatcher) MaxUsage

func (d *Dispatcher) MaxUsage() int

MaxUsage returns the maximum number of concurrently processing updates.

func (*Dispatcher) ProcessUpdate

func (d *Dispatcher) ProcessUpdate(b *gotgbot.Bot, u *gotgbot.Update, data map[string]interface{}) (err error)

ProcessUpdate iterates over the list of groups to execute the matching handlers. This is also where we recover from any panics that are thrown by user code, to avoid taking down the bot.

func (*Dispatcher) RemoveGroup

func (d *Dispatcher) RemoveGroup(group int) bool

RemoveGroup removes an entire group from the dispatcher's processing. If group can't be found, this is a noop.

func (*Dispatcher) RemoveHandlerFromGroup

func (d *Dispatcher) RemoveHandlerFromGroup(handlerName string, group int) bool

RemoveHandlerFromGroup removes a handler by name from the specified group. If multiple handlers have the same name, only the first one is removed. Returns true if the handler was successfully removed.

func (*Dispatcher) Start

func (d *Dispatcher) Start(b *gotgbot.Bot, updates <-chan json.RawMessage)

Start to handle incoming updates. This is a blocking method; it should be called as a goroutine, such that it can receive incoming updates.

func (*Dispatcher) Stop

func (d *Dispatcher) Stop()

Stop waits for all currently processing updates to finish, and then returns.

type DispatcherAction

type DispatcherAction string
const (
	// DispatcherActionNoop stops iteration of current group and moves to the next one.
	// This is the default action, and the same as would happen if the handler had completed successfully.
	DispatcherActionNoop DispatcherAction = "noop"
	// DispatcherActionContinueGroups continues iterating over current group as if the current handler did not match.
	// Functionally the same as returning ContinueGroups.
	DispatcherActionContinueGroups DispatcherAction = "continue-groups"
	// DispatcherActionEndGroups ends all group iteration.
	// Functionally the same as returning EndGroups.
	DispatcherActionEndGroups DispatcherAction = "end-groups"
)

type DispatcherErrorHandler

type DispatcherErrorHandler func(b *gotgbot.Bot, ctx *Context, err error) DispatcherAction

DispatcherErrorHandler allows for handling the returned errors from matched handlers. It takes the non-nil error returned by the handler.

type DispatcherOpts

type DispatcherOpts struct {
	// Processor allows for providing custom Processor interfaces with different behaviours.
	Processor Processor
	// Error handles any errors that occur during handler execution.
	// More info at Dispatcher.Error.
	Error DispatcherErrorHandler
	// Panic handles any panics that occur during handler execution.
	// If no panic handlers are defined, the stack is logged to ErrorLog.
	// More info at Dispatcher.Panic.
	Panic DispatcherPanicHandler

	// UnhandledErrFunc provides more flexibility for dealing with unhandled update processing errors.
	// This includes errors when unmarshalling updates, unhandled panics during handler executions, or unknown
	// dispatcher actions.
	// If nil, the error goes to ErrorLog.
	UnhandledErrFunc ErrorFunc
	// ErrorLog specifies an optional logger for unexpected behavior from handlers.
	// If nil, logging is done via the log package's standard logger.
	ErrorLog *log.Logger

	// MaxRoutines is used to decide how to limit the number of goroutines spawned by the dispatcher.
	// This defines how many updates can be processed at the same time.
	// If MaxRoutines == 0, DefaultMaxRoutines is used instead.
	// If MaxRoutines < 0, no limits are imposed.
	// If MaxRoutines > 0, that value is used.
	MaxRoutines int
}

DispatcherOpts can be used to configure or override default Dispatcher behaviours.

type DispatcherPanicHandler

type DispatcherPanicHandler func(b *gotgbot.Bot, ctx *Context, r interface{})

DispatcherPanicHandler allows for handling goroutine panics, where the 'r' value contains the reason for the panic.

type ErrorFunc

type ErrorFunc func(error)

type Handler

type Handler interface {
	// CheckUpdate checks whether the update should handled by this handler.
	CheckUpdate(b *gotgbot.Bot, ctx *Context) bool
	// HandleUpdate processes the update.
	HandleUpdate(b *gotgbot.Bot, ctx *Context) error
	// Name gets the handler name; used to differentiate handlers programmatically. Names should be unique.
	Name() string
}

type PollingOpts

type PollingOpts struct {
	// DropPendingUpdates toggles whether to drop updates which were sent before the bot was started.
	// This also implicitly enables webhook deletion.
	DropPendingUpdates bool
	// EnableWebhookDeletion deletes any existing webhooks to ensure that the updater works fine.
	EnableWebhookDeletion bool
	// GetUpdatesOpts represents the opts passed to GetUpdates.
	// Note: It is recommended you edit the values here when running in production environments.
	// Suggestions include:
	//    - Changing the "GetUpdatesOpts.AllowedUpdates" to only refer to updates relevant to your bot's functionality.
	//    - Using a non-0 "GetUpdatesOpts.Timeout" value. This is how "long" telegram will hold the long-polling call
	//    while waiting for new messages. A value of 0 causes telegram to reply immediately, which will then cause
	//    your bot to immediately ask for more updates. While this can seem fine, it will eventually causing
	//    telegram to delay your requests when left running over longer periods. If you are seeing lots
	//    of "context deadline exceeded" errors on GetUpdates, this is likely the cause.
	//    Keep in mind that a timeout of 10 does not mean you only get updates every 10s; by the nature of
	//    long-polling, Telegram responds to your request as soon as new messages are available.
	//    When setting this, it is recommended you set your PollingOpts.Timeout value to be slightly bigger (eg, +1).
	GetUpdatesOpts *gotgbot.GetUpdatesOpts
}

PollingOpts represents the optional values to start long polling.

type Processor

type Processor interface {
	ProcessUpdate(d *Dispatcher, b *gotgbot.Bot, ctx *Context) error
}

Processor is used to provide an entry point for wrapping internal Dispatcher logic, such that the basic logic can be customised and extended.

type UpdateDispatcher

type UpdateDispatcher interface {
	Start(b *gotgbot.Bot, updates <-chan json.RawMessage)
	Stop()
}

The UpdateDispatcher interface is used to abstract away common Dispatcher implementations. It assumes that all incoming updates come through a JSON channel.

type Updater

type Updater struct {
	// Dispatcher is where all the incoming updates are sent to be processed.
	// The Dispatcher runs in a separate goroutine, allowing for parallel update processing and dispatching.
	// Once the Updater has received an update, it sends it to the Dispatcher over a JSON channel.
	Dispatcher UpdateDispatcher

	// UnhandledErrFunc provides more flexibility for dealing with previously unhandled errors, such as failures to get
	// updates (when long-polling), or failures to unmarshal.
	// If nil, the error goes to ErrorLog.
	UnhandledErrFunc ErrorFunc
	// ErrorLog specifies an optional logger for unexpected behavior from handlers.
	// If nil, logging is done via the log package's standard logger.
	ErrorLog *log.Logger
	// contains filtered or unexported fields
}

func NewUpdater

func NewUpdater(dispatcher UpdateDispatcher, opts *UpdaterOpts) *Updater

NewUpdater Creates a new Updater, as well as a Dispatcher and any optional updater configurations (via UpdaterOpts).

func (*Updater) AddWebhook

func (u *Updater) AddWebhook(b *gotgbot.Bot, urlPath string, opts *AddWebhookOpts) error

AddWebhook prepares the webhook server to receive webhook updates for one bot, on a specific path.

func (*Updater) GetHandlerFunc

func (u *Updater) GetHandlerFunc(pathPrefix string) http.HandlerFunc

GetHandlerFunc returns the http.HandlerFunc responsible for processing incoming webhook updates. It is provided to allow for an alternative to the StartServer method using a user-defined http server.

func (*Updater) Idle

func (u *Updater) Idle()

Idle starts an infinite loop to avoid the program exciting while the background threads handle updates.

func (*Updater) SetAllBotWebhooks

func (u *Updater) SetAllBotWebhooks(domain string, opts *gotgbot.SetWebhookOpts) error

SetAllBotWebhooks sets all the webhooks for the bots that have been added to this updater via AddWebhook.

func (*Updater) StartPolling

func (u *Updater) StartPolling(b *gotgbot.Bot, opts *PollingOpts) error

StartPolling starts polling updates from telegram using getUpdates long-polling. See PollingOpts for optional values to set in production environments.

func (*Updater) StartServer

func (u *Updater) StartServer(opts WebhookOpts) error

StartServer starts the webhook server for all the bots added via AddWebhook. It is recommended to call this BEFORE calling setWebhooks. The opts parameter allows for specifying TLS settings.

func (*Updater) StartWebhook

func (u *Updater) StartWebhook(b *gotgbot.Bot, urlPath string, opts WebhookOpts) error

StartWebhook starts the webhook server for a single bot instance. This does NOT set the webhook on telegram - this should be done by the caller. The opts parameter allows for specifying various webhook settings.

func (*Updater) Stop

func (u *Updater) Stop() error

Stop stops the current updater and dispatcher instances.

When using long polling, Stop() will wait for the getUpdates call to return, which may cause a delay due to the request timeout.

func (*Updater) StopAllBots

func (u *Updater) StopAllBots()

func (*Updater) StopBot

func (u *Updater) StopBot(token string) bool

type UpdaterOpts

type UpdaterOpts struct {
	// UnhandledErrFunc provides more flexibility for dealing with previously unhandled errors, such as failures to get
	// updates (when long-polling), or failures to unmarshal.
	// If nil, the error goes to ErrorLog.
	UnhandledErrFunc ErrorFunc
	// ErrorLog specifies an optional logger for unexpected behavior from handlers.
	// If nil, logging is done via the log package's standard logger.
	ErrorLog *log.Logger
}

UpdaterOpts defines various fields that can be changed to configure a new Updater.

type WebhookOpts

type WebhookOpts struct {
	// ListenAddr is the address and port to listen on (eg: localhost:http, 0.0.0.0:8080, :https, "[::1]:", etc).
	// See the net package for details.
	ListenAddr string
	// ListenNet is the network type to listen on (must be "tcp", "tcp4", "tcp6", "unix" or "unixpacket").
	// Empty means the default, "tcp".
	ListenNet string
	// ReadTimeout is passed to the http server to limit the time it takes to read an incoming request.
	// See http.Server for more details.
	ReadTimeout time.Duration
	// ReadHeaderTimeout is passed to the http server to limit the time it takes to read the headers of an incoming
	// request.
	// See http.Server for more details.
	ReadHeaderTimeout time.Duration

	// HTTPS cert and key files for custom signed certificates
	CertFile string
	KeyFile  string

	// SecretToken to be used by the bots on this webhook. Used as a security measure to ensure that you set the webhook.
	SecretToken string
}

WebhookOpts represent various fields that are needed for configuring the local webhook server.

func (*WebhookOpts) GetListenNet

func (w *WebhookOpts) GetListenNet() string

Jump to

Keyboard shortcuts

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