tbb

package module
v0.5.2 Latest Latest
Warning

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

Go to latest
Published: Sep 10, 2024 License: MIT Imports: 24 Imported by: 0

README

Telegram Bot Builder (tbb)

Tbb aims to provide a starting point for building Telegram bots in go. The Telegram Bot Builder is based on the concurrent library NicoNex/echotron. To spin up a bot on your own see the examples section for details.

Go Report Card GitHub go.mod Go version GitHub Licence

  • Starting point for your own Telegram bot.
  • Easily extendable.
  • Implements Telegram bot user handling in either sqlite (default), mysql or postgres.
  • Time zone handling by coordinates: Can use a location message from a user to set the current user time zone and offset from UTC.

How to use tbb

  1. Create a new go project by go mod init.
  2. Run go get github.com/apperia-de/tbb.
  3. Create a new file config.yml with the contents from example.config.yml.
  4. Adjust values to your needs, especially provide your Telegram.BotToken, which you may get from @botfather bot.
  5. See example.

Example

Telegram bot
package main

import (
	"github.com/apperia-de/tbb"
	"github.com/apperia-de/tbb/command"
)

func main() {
	// Load your Telegram bot config (@see example.config.yml)
	cfg := tbb.LoadConfig('config.yml')
	app := tbb.NewApp(
		tbb.WithConfig(&cfg),
		tbb.WithCommands([]tbb.Command{
			{
				Name:        "/start",
				Description: "",
				Handler:     &command.Enable{},
			}, {
				Name:        "/enable",
				Description: "Enable bot notifications",
				Handler:     &command.Enable{},
			},
			{
				Name:        "/disable",
				Description: "Disable bot notifications",
				Handler:     &command.Disable{},
			},
			{
				Name:        "/timezone",
				Description: "Set your current time zone",
				Handler:     &command.Timezone{},
			},
			{
				Name:        "/help",
				Description: "Show the help message",
				Handler:     &command.Help{},
			},
		}),
	)
	
	app.Start() // Start a new bot polling for updates
}
example.config.yml
##############################################
# Telegram Bot Builder example configuration #
##############################################

debug: true
logLevel: info # One of debug | info | warn | error
telegram:
  botToken: "YOUR_TELEGRAM_BOT_TOKEN" # Enter your Telegram bot token which can be obtained from https://telegram.me/botfather
database:
  type: sqlite # One of sqlite | postgres | mysql
  filename: "app.db" # Only required for type sqlite
  #dsn: "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local" # Only required for type postgres or mysql
botSessionTimeout: 5 # Timeout in minutes before bot sessions will be deleted to save memory.

For an example of how to implement your own UpdateHandler see cmd/example/main.go

Documentation

Overview

Package tbb provides a base for creating custom Telegram bots. It can be used to spin up a custom bot in one minute which is capable of handling bot users via an implemented sqlite database, but can easily be switched to use mysql or postgres instead.

Index

Examples

Constants

View Source
const (
	DB_TYPE_SQLITE   = "sqlite"
	DB_TYPE_MYSQL    = "mysql"
	DB_TYPE_POSTGRES = "postgres"
)

Variables

This section is empty.

Functions

func BuildInlineKeyboardButtonRow

func BuildInlineKeyboardButtonRow(buttons []InlineKeyboardButton) []echotron.InlineKeyboardButton

BuildInlineKeyboardButtonRow helper function for creating Telegram inline keyboards

func GetUserFromUpdate

func GetUserFromUpdate(u *echotron.Update) echotron.User

GetUserFromUpdate returns the echotron.User from a given echotron.Update

func PrintAsJson

func PrintAsJson(v any, indent bool) string

PrintAsJson returns the JSON representation of a given go struct.

Types

type App

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

func NewApp

func NewApp(opts ...AppOption) *App

NewApp creates a new Telegram bot based on the given configuration. It uses functional options for configuration.

Example
package main

import (
	"github.com/apperia-de/tbb"
)

func main() {
	type CustomConfig struct {
		Version   string   `yaml:"version"`
		Blacklist []string `yaml:"blacklist"`
	}

	cfg := tbb.LoadCustomConfig[CustomConfig]("config.yml")

	app := tbb.NewApp(tbb.WithConfig(cfg))
	app.Start()
}

func (*App) API

func (a *App) API() echotron.API

API returns the reference to the echotron.API.

func (*App) Config added in v0.2.0

func (a *App) Config() *Config

Config returns the config

func (*App) DB

func (a *App) DB() *DB

DB returns the database handle for the bot so that the database can easily be adjusted and extended.

func (*App) GetCurrentTimeOffset

func (a *App) GetCurrentTimeOffset(lat, lon float64) int

GetCurrentTimeOffset returns the time offset in seconds for the given coordinates or zero if no time zone info may be obtained from coordinates.

func (*App) GetTimezoneInfo

func (a *App) GetTimezoneInfo(lat, lon float64) (*TZInfo, error)

GetTimezoneInfo returns the time zone info for the given coordinates if available.

func (*App) SetBotCommands

func (a *App) SetBotCommands(bc []echotron.BotCommand) error

SetBotCommands registers the given command list for your Telegram bot. Will delete registered bot commands if parameter bc is nil.

func (*App) Start

func (a *App) Start()

Start starts the Telegram bot server in poll mode

func (*App) StartWithWebhook

func (a *App) StartWithWebhook(webhookURL string)

StartWithWebhook starts the Telegram bot server with a given webhook url.

type AppOption

type AppOption func(*App)

func WithCommands

func WithCommands(commands []Command) AppOption

WithCommands is used for providing and registering custom bot commands. Bot commands always start with a / like /start and a Handler, which implements the CommandHandler interface. If you want a command to be available in the command list on Telegram, the provided Command must contain a Description.

func WithConfig

func WithConfig(cfg *Config) AppOption

WithConfig is the only required option because it provides the config for the app to function properly.

func WithHandlerFunc

func WithHandlerFunc(hFn UpdateHandlerFn) AppOption

WithHandlerFunc option can be used to override the default UpdateHandlerFn for custom echotron.Update message handling.

func WithLogger

func WithLogger(l *slog.Logger) AppOption

WithLogger option can be used to override the default logger with a custom one.

type Bot

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

func (*Bot) API

func (b *Bot) API() echotron.API

API returns the echotron.API

func (*Bot) App

func (b *Bot) App() *App

App returns the App reference

func (*Bot) ChatID

func (b *Bot) ChatID() int64

ChatID returns the user chatID

func (*Bot) Command

func (b *Bot) Command() *Command

Command returns the last command that was sent by the user

func (*Bot) DB

func (b *Bot) DB() *DB

DB Returns the database reference

func (*Bot) DeleteMessage

func (b *Bot) DeleteMessage(q *echotron.CallbackQuery)

DeleteMessage deletes the given CallbackQuery message

func (*Bot) DisableUser

func (b *Bot) DisableUser()

DisableUser disable the current user and update the database

func (*Bot) EnableUser

func (b *Bot) EnableUser()

EnableUser enables the current user and updates the database

func (*Bot) GetUsersTimezoneOffset

func (b *Bot) GetUsersTimezoneOffset() (int, error)

GetUsersTimezoneOffset returns the time zone offset in seconds if the user has already provided coordinates. This can be used, for example, to calculate the current time of the user.

func (*Bot) IsUserActive

func (b *Bot) IsUserActive() bool

IsUserActive returns true if the user is active or false otherwise

func (*Bot) Log

func (b *Bot) Log() *slog.Logger

Log can be used to access the logger.

func (*Bot) ReplaceMessage

func (b *Bot) ReplaceMessage(q *echotron.CallbackQuery, text string, buttons [][]echotron.InlineKeyboardButton)

ReplaceMessage replaces the given CallbackQuery message with new Text and Keyboard

func (*Bot) Update

func (b *Bot) Update(u *echotron.Update)

Update is called whenever a Telegram update occurs

func (*Bot) User

func (b *Bot) User() *model.User

User returns the User associated with the bot

type ChatType added in v0.5.0

type ChatType string
const (
	ChatTypePrivate    ChatType = "private"
	ChatTypeChannel    ChatType = "channel"
	ChatTypeGroup      ChatType = "group"
	ChatTypeSuperGroup ChatType = "supergroup"
	ChatTypeUnknown    ChatType = "unknown"
)

func GetChatTypeFromUpdate added in v0.5.0

func GetChatTypeFromUpdate(u *echotron.Update) ChatType

GetChatTypeFromUpdate returns the ChatType from a given echotron.Update

type Command

type Command struct {
	Name        string
	Description string
	Params      []string
	Data        any
	Handler     CommandHandler
}

type CommandHandler

type CommandHandler interface {
	Bot() *Bot
	SetBot(*Bot)
	Handle() StateFn
}

type CommandRegistry

type CommandRegistry map[string]Command

type Config

type Config struct {
	Admin struct {
		BotToken string  `yaml:"botToken"` // Telegram bot token for an admin bot to use when sending messages
		ChatIDs  []int64 `yaml:"chatIDs"`  // Telegram chat IDs of admins
	} `yaml:"admin"`
	AllowedChatIDs []int64 `yaml:"allowedChatIDs"` // If set, only the specified chatIDs are allowed to use the bot. If not set or empty, all chat ids are allowed to use the bot.
	Database       struct {
		Type     string `yaml:"type"`     // one of sqlite, mysql, postgres
		DSN      string `yaml:"dsn"`      // in the case of mysql or postgres
		Filename string `yaml:"filename"` // in the case of sqlite
	} `yaml:"database"`
	Debug             bool   `yaml:"debug"`
	BotSessionTimeout int    `yaml:"botSessionTimeout"` // Timeout in minutes, after which the bot instance will be deleted to save memory. Defaults to 15 minutes.
	LogLevel          string `yaml:"logLevel"`
	Telegram          struct {
		BotToken string `yaml:"botToken"`
	} `yaml:"telegram"`
	CustomData any `yaml:"customData"`
}

func LoadConfig

func LoadConfig(filename string) *Config

LoadConfig returns the yaml config with the given name

func LoadCustomConfig added in v0.2.0

func LoadCustomConfig[T any](filename string) *Config

LoadCustomConfig returns the config but also takes your custom struct for the "customData" into account.

type DB

type DB struct {
	*gorm.DB
}

func NewDB added in v0.5.1

func NewDB(cfg *Config, gormCfg *gorm.Config) *DB

NewDB returns a new Database connection based on the given config files

func (*DB) FindUserByChatID

func (db *DB) FindUserByChatID(chatID int64) (*model.User, error)

FindUserByChatID return a user by Telegram chat id if exists or error otherwise.

type DefaultCommandHandler

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

func (*DefaultCommandHandler) Bot

func (h *DefaultCommandHandler) Bot() *Bot

func (*DefaultCommandHandler) Handle

func (h *DefaultCommandHandler) Handle() StateFn

func (*DefaultCommandHandler) SetBot added in v0.4.0

func (h *DefaultCommandHandler) SetBot(bot *Bot)

type DefaultUpdateHandler

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

DefaultUpdateHandler implements the UpdateHandler interface

func (*DefaultUpdateHandler) Bot

func (h *DefaultUpdateHandler) Bot() *Bot

func (*DefaultUpdateHandler) HandleCallbackQuery

func (h *DefaultUpdateHandler) HandleCallbackQuery(c echotron.CallbackQuery) StateFn

func (*DefaultUpdateHandler) HandleChannelPost

func (h *DefaultUpdateHandler) HandleChannelPost(m echotron.Message) StateFn

func (*DefaultUpdateHandler) HandleChatJoinRequest

func (h *DefaultUpdateHandler) HandleChatJoinRequest(c echotron.ChatJoinRequest) StateFn

func (*DefaultUpdateHandler) HandleChatMember

func (h *DefaultUpdateHandler) HandleChatMember(c echotron.ChatMemberUpdated) StateFn

func (*DefaultUpdateHandler) HandleChosenInlineResult

func (h *DefaultUpdateHandler) HandleChosenInlineResult(c echotron.ChosenInlineResult) StateFn

func (*DefaultUpdateHandler) HandleEditedChannelPost

func (h *DefaultUpdateHandler) HandleEditedChannelPost(m echotron.Message) StateFn

func (*DefaultUpdateHandler) HandleEditedMessage

func (h *DefaultUpdateHandler) HandleEditedMessage(m echotron.Message) StateFn

func (*DefaultUpdateHandler) HandleInlineQuery

func (h *DefaultUpdateHandler) HandleInlineQuery(i echotron.InlineQuery) StateFn

func (*DefaultUpdateHandler) HandleMessage

func (h *DefaultUpdateHandler) HandleMessage(m echotron.Message) StateFn

func (*DefaultUpdateHandler) HandleMyChatMember

func (h *DefaultUpdateHandler) HandleMyChatMember(c echotron.ChatMemberUpdated) StateFn

func (*DefaultUpdateHandler) HandlePreCheckoutQuery

func (h *DefaultUpdateHandler) HandlePreCheckoutQuery(p echotron.PreCheckoutQuery) StateFn

func (*DefaultUpdateHandler) HandleShippingQuery

func (h *DefaultUpdateHandler) HandleShippingQuery(s echotron.ShippingQuery) StateFn

func (*DefaultUpdateHandler) SetBot

func (h *DefaultUpdateHandler) SetBot(bot *Bot)

type InlineKeyboardButton

type InlineKeyboardButton struct {
	Text string `json:"text"`
	Data string `json:"data"`
}

type StateFn

type StateFn func(*echotron.Update) StateFn

type TZInfo

type TZInfo struct {
	Latitude  float64
	Longitude float64
	Location  string
	ZoneName  string
	IsDST     bool
	Offset    int
}

type UpdateHandler

type UpdateHandler interface {
	Bot() *Bot
	SetBot(*Bot)
	HandleMessage(echotron.Message) StateFn
	HandleEditedMessage(echotron.Message) StateFn
	HandleChannelPost(echotron.Message) StateFn
	HandleEditedChannelPost(echotron.Message) StateFn
	HandleInlineQuery(echotron.InlineQuery) StateFn
	HandleChosenInlineResult(echotron.ChosenInlineResult) StateFn
	HandleCallbackQuery(echotron.CallbackQuery) StateFn
	HandleShippingQuery(echotron.ShippingQuery) StateFn
	HandlePreCheckoutQuery(echotron.PreCheckoutQuery) StateFn
	HandleChatMember(echotron.ChatMemberUpdated) StateFn
	HandleMyChatMember(echotron.ChatMemberUpdated) StateFn
	HandleChatJoinRequest(echotron.ChatJoinRequest) StateFn
}

type UpdateHandlerFn

type UpdateHandlerFn func() UpdateHandler

Directories

Path Synopsis
cmd
example command
timezone command
pkg

Jump to

Keyboard shortcuts

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