tbb

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Aug 28, 2024 License: MIT Imports: 21 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.

Features

  • Starting point for your own Telegram bot.
  • Implements Telegram Bot user handling in either sqlite (default), mysql or postgres.
  • Easily extendable.
  • Fast implementation of new Telegram bots.
  • Time zone handling by coordinates: Can used 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

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 GetLogLevel

func GetLogLevel(level string) slog.Level

GetLogLevel converts string log levels to slog.Level representation. Can be one of "debug", "info", "warn" or "error".

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.

func (*App) API

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

API returns the reference to the echotron.API.

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) DeleteBotCommands

func (a *App) DeleteBotCommands() error

DeleteBotCommands removes the registered Telegram commands from your bot.

func (*App) GetCurrentTimeOffset

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

GetCurrentTimeOffset returns the time offset in seconds for the given coordinates

func (*App) GetTimezoneInfo

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

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.

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

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 current user and updates the database

func (*Bot) EnableUser

func (b *Bot) EnableUser()

EnableUser enables current user and updates the database

func (*Bot) GetUsernameFromMessage

func (b *Bot) GetUsernameFromMessage(m *echotron.Message) string

GetUsernameFromMessage returns the Firstname or Username from the telegram user of the given message

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

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() *User

User returns the User associated with the bot

type BotOption

type BotOption func(*Bot)

type Command

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

type CommandFunc

type CommandFunc func(*Bot, Command, *echotron.Update) StateFn

type CommandHandler

type CommandHandler interface {
	Handle(*Bot) StateFn
}

type CommandRegistry

type CommandRegistry map[string]Command

type Config

type Config struct {
	Admin struct {
		BotToken string `yaml:"botToken"`
		ChatID   int64  `yaml:"chatID"`
	} `yaml:"admin"`
	Database struct {
		Type     string `yaml:"type"`     // one of sqlite, mysql, postgres
		DSN      string `yaml:"dsn"`      // in case of mysql or postgres
		Filename string `yaml:"filename"` // in case of sqlite
	} `yaml:"database"`
	Debug             bool   `yaml:"debug"`
	BotSessionTimeout int    `yaml:"botSessionTimeout"` // Timeout in minutes after which the bot instance will be deleted in order to save memory. Defaults to 15 minutes.
	LogLevel          string `yaml:"logLevel"`
	Telegram          struct {
		BotToken string `yaml:"botToken"`
	} `yaml:"telegram"`
}

func LoadConfig

func LoadConfig(filename string) Config

type DB

type DB struct {
	*gorm.DB
	// contains filtered or unexported fields
}

func (*DB) FindUserByChatID

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

type DefaultCommandHandler

type DefaultCommandHandler struct {
	Bot *Bot
}

func (*DefaultCommandHandler) Handle

func (h *DefaultCommandHandler) Handle(bot *Bot) StateFn

type DefaultUpdateHandler

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

DefaultUpdateHandler implements the UpdateHandler interface

func (*DefaultUpdateHandler) Bot

func (d *DefaultUpdateHandler) Bot() *Bot

func (*DefaultUpdateHandler) HandleCallbackQuery

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

func (*DefaultUpdateHandler) HandleChannelPost

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

func (*DefaultUpdateHandler) HandleChatJoinRequest

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

func (*DefaultUpdateHandler) HandleChatMember

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

func (*DefaultUpdateHandler) HandleChosenInlineResult

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

func (*DefaultUpdateHandler) HandleEditedChannelPost

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

func (*DefaultUpdateHandler) HandleEditedMessage

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

func (*DefaultUpdateHandler) HandleInlineQuery

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

func (*DefaultUpdateHandler) HandleMessage

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

func (*DefaultUpdateHandler) HandleMyChatMember

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

func (*DefaultUpdateHandler) HandlePreCheckoutQuery

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

func (*DefaultUpdateHandler) HandleShippingQuery

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

func (*DefaultUpdateHandler) SetBot

func (d *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

type User

type User struct {
	ID           uint64     `gorm:"primaryKey" json:"-"`
	Username     string     `json:"username"`
	Firstname    string     `json:"firstname"`
	Lastname     string     `json:"lastname"`
	IsBot        bool       `json:"isBot"`                // True if user is itself a Bot
	ChatID       int64      `gorm:"unique" json:"chatID"` // Telegram chatID of the user
	LanguageCode string     `json:"language_code"`        // Language code of the user
	IsPremium    bool       `json:"isPremium"`            // True, if this user is a Telegram Premium user
	UserInfo     *UserInfo  `json:"userInfo,omitempty"`
	UserPhoto    *UserPhoto `json:"-"`
	CreatedAt    time.Time
	UpdatedAt    time.Time
}

type UserInfo

type UserInfo struct {
	UserID    uint64 `gorm:"primaryKey"`
	IsActive  bool
	Status    string  // Either "member" or "kicked"
	Latitude  float64 // Latitude the user sends for determining the users current Time zone
	Longitude float64 // Longitude the user sends for determining the users current Time zone
	Location  string  // Location of the user's timezone
	ZoneName  string  // Zone name of the user's timezone
	TZOffset  *int    // Time zone offset in seconds
	IsDST     bool    // Whether the TZOffset is in daylight saving time or normal time
	CreatedAt time.Time
	UpdatedAt time.Time
}

type UserPhoto

type UserPhoto struct {
	UserID       uint64 `gorm:"primaryKey"` // ID from User table to whom the photo belongs to.
	FileID       string // Identifier for this file, which can be used to download or reuse the file
	FileUniqueID string // Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file.
	FileSize     int    // Size in bytes of the user photo
	FileHash     string // The md5 file hash of the user photo
	FileData     []byte // The binary Data of the user photo
	Width        int    // Photo width
	Height       int    // Photo height
	CreatedAt    time.Time
	UpdatedAt    time.Time
}

Directories

Path Synopsis
cmd
example command
timezone command

Jump to

Keyboard shortcuts

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