### Initialize and Start a Bote Telegram Bot Source: https://github.com/maxbolgarin/bote/blob/main/README.md Demonstrates the basic setup of a Bote bot, including context-based signal handling and defining interactive handlers with inline keyboards. ```go package main import ( "context" "log" "os" "os/signal" "syscall" "github.com/maxbolgarin/bote" ) func main() { token := os.Getenv("TELEGRAM_BOT_TOKEN") if token == "" { log.Fatalln("TELEGRAM_BOT_TOKEN is not set") } ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer cancel() b, err := bote.New(ctx, token) if err != nil { log.Fatalln(err) } stopCh := b.Start(ctx, startHandler, nil) <-stopCh } func startHandler(ctx bote.Context) error { kb := bote.InlineBuilder(3, bote.OneBytePerRune, ctx.Btn("Option 1", option1Handler), ctx.Btn("Option 2", option2Handler), ctx.Btn("Option 3", option3Handler), ) return ctx.SendMain(bote.NoChange, "Welcome! Choose an option:", kb) } ``` -------------------------------- ### Todo Bot Example using Go Source: https://context7.com/maxbolgarin/bote/llms.txt A complete example demonstrating how to build a Todo bot using the Bote framework. It showcases state management, text input handling, user value persistence, and inline keyboard interactions. ```go package main import ( "context" "fmt" "log" "os" "os/signal" "syscall" "github.com/maxbolgarin/bote" ) type State string func (s State) String() string { return string(s) } func (s State) IsText() bool { return s == StateAddingTask } func (s State) NotChanged() bool { return false } const ( StateMenu State = "menu" StateAddingTask State = "adding_task" StateViewTasks State = "view_tasks" ) func main() { ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer cancel() b, err := bote.New(ctx, os.Getenv("TELEGRAM_BOT_TOKEN")) if err != nil { log.Fatalln(err) } b.SetTextHandler(textHandler) stopCh := b.Start(ctx, menuHandler, map[bote.State]bote.InitBundle{ StateMenu: {Handler: menuHandler}, StateAddingTask: {Handler: addTaskHandler}, StateViewTasks: {Handler: viewTasksHandler}, }) <-stopCh } func menuHandler(ctx bote.Context) error { kb := bote.InlineBuilder(1, bote.OneBytePerRune, ctx.Btn("➕ Add Task", addTaskHandler), ctx.Btn("📋 View Tasks", viewTasksHandler), ) return ctx.SendMain(StateMenu, bote.FB("Todo List")+"\nChoose an action:", kb) } func addTaskHandler(ctx bote.Context) error { kb := bote.SingleRow(ctx.Btn("Cancel", menuHandler)) return ctx.EditMain(StateAddingTask, "Enter your task:", kb) } func viewTasksHandler(ctx bote.Context) error { tasks, ok := ctx.User().GetValue("tasks") if !ok || len(tasks.([]string)) == 0 { kb := bote.SingleRow(ctx.Btn("Add Task", addTaskHandler)) return ctx.EditMain(StateViewTasks, "No tasks yet!", kb) } b := bote.NewBuilder() b.Writeln(bote.FB("Your Tasks:")) b.Writeln("") for i, task := range tasks.([]string) { b.Writeln(fmt.Sprintf("%d. %s", i+1, task)) } kb := bote.InlineBuilder(1, bote.OneBytePerRune, ctx.Btn("➕ Add Task", addTaskHandler), ctx.Btn("🗑 Clear All", clearTasksHandler), ctx.Btn("⬅️ Back", menuHandler), ) return ctx.EditMain(StateViewTasks, b.String(), kb) } func clearTasksHandler(ctx bote.Context) error { ctx.User().DeleteValue("tasks") return viewTasksHandler(ctx) } func textHandler(ctx bote.Context) error { if ctx.User().StateMain() != StateAddingTask { return nil } task := ctx.Text() tasks, ok := ctx.User().GetValue("tasks") var list []string if ok { list = tasks.([]string) } list = append(list, task) ctx.User().SetValue("tasks", list) ctx.SendNotification("✅ Task added: "+bote.FI(task), nil) return viewTasksHandler(ctx) } ``` -------------------------------- ### Create and Start a Bote Telegram Bot in Go Source: https://context7.com/maxbolgarin/bote/llms.txt Demonstrates how to initialize a new Bote bot instance with custom configurations like language, logger, user database, and message providers. It also shows how to start the bot with a main handler and define states for restart recovery. ```go package main import ( "context" "log" "os" "os/signal" "syscall" "github.com/maxbolgarin/bote" ) func main() { token := os.Getenv("TELEGRAM_BOT_TOKEN") if token == "" { log.Fatalln("TELEGRAM_BOT_TOKEN is not set") } ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer cancel() // Create bot with options b, err := bote.New(ctx, token, bote.WithDefaultLanguage("en"), bote.WithLogger(myLogger), bote.WithUserDB(myStorage), bote.WithMsgsProvider(myMessages), ) if err != nil { log.Fatalln(err) } // Start bot with start handler and state map for restart recovery stopCh := b.Start(ctx, startHandler, map[bote.State]bote.InitBundle{ StateMenu: {Handler: menuHandler}, StateSettings: {Handler: settingsHandler}, }) <-stopCh } func startHandler(ctx bote.Context) error { kb := bote.InlineBuilder(3, bote.OneBytePerRune, ctx.Btn("Option 1", option1Handler), ctx.Btn("Option 2", option2Handler), ctx.Btn("Option 3", option3Handler), ) return ctx.SendMain(bote.NoChange, "Welcome! Choose an option:", kb) } ``` -------------------------------- ### Complete Todo Bot Example using Bote Source: https://github.com/maxbolgarin/bote/blob/main/README.md A full-fledged example of a Todo bot demonstrating Bote's capabilities. It includes state management for different user interactions (menu, adding tasks, viewing tasks), handling text input, and using inline keyboards for navigation and actions. The bot stores tasks in user session data. ```go package main import ( "context" "fmt" "log" "os" "os/signal" "strconv" "syscall" "github.com/maxbolgarin/bote" ) type State string func (s State) String() string { return string(s) } func (s State) IsText() bool { return s == StateAddingTask } func (s State) NotChanged() bool { return false } const ( StateMenu State = "menu" StateAddingTask State = "adding_task" StateViewTasks State = "view_tasks" ) func main() { ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer cancel() b, err := bote.New(ctx, os.Getenv("TELEGRAM_BOT_TOKEN")) if err != nil { log.Fatalln(err) } b.SetTextHandler(textHandler) stopCh := b.Start(ctx, menuHandler, map[bote.State]bote.InitBundle{ StateMenu: {Handler: menuHandler}, StateAddingTask: {Handler: addTaskHandler}, StateViewTasks: {Handler: viewTasksHandler}, }) <-stopCh } func menuHandler(ctx bote.Context) error { kb := bote.InlineBuilder(1, bote.OneBytePerRune, ctx.Btn("Add Task", addTaskHandler), ctx.Btn("View Tasks", viewTasksHandler), ) return ctx.SendMain(StateMenu, bote.FB("Todo List")+"\nChoose an action:", kb) } func addTaskHandler(ctx bote.Context) error { kb := bote.SingleRow(ctx.Btn("Cancel", menuHandler)) return ctx.EditMain(StateAddingTask, "Enter your task:", kb) } func viewTasksHandler(ctx bote.Context) error { tasks, ok := ctx.User().GetValue("tasks") if !ok || len(tasks.([]string)) == 0 { kb := bote.SingleRow(ctx.Btn("Add Task", addTaskHandler)) return ctx.EditMain(StateViewTasks, "No tasks yet!", kb) } b := bote.NewBuilder() b.Writeln(bote.FB("Your Tasks:")) b.Writeln("") for i, task := range tasks.([]string) { b.Writeln(fmt.Sprintf("%d. %s", i+1, task)) } kb := bote.InlineBuilder(1, bote.OneBytePerRune, ctx.Btn("Add Task", addTaskHandler), ctx.Btn("Clear All", func(ctx bote.Context) error { ctx.User().DeleteValue("tasks") return viewTasksHandler(ctx) }), ctx.Btn("Back", menuHandler), ) return ctx.EditMain(StateViewTasks, b.String(), kb) } func textHandler(ctx bote.Context) error { if ctx.User().StateMain() != StateAddingTask { return nil } task := ctx.Text() tasks, ok := ctx.User().GetValue("tasks") var list []string if ok { list = tasks.([]string) } list = append(list, task) ctx.User().SetValue("tasks", list) ctx.SendNotification("Task added: "+bote.FI(task), nil) return viewTasksHandler(ctx) } ``` -------------------------------- ### Configure Webhook Mode for Production in Go Source: https://context7.com/maxbolgarin/bote/llms.txt Illustrates setting up webhook mode for a Bote bot, suitable for production deployments. It covers basic webhook URL and port configuration, security options like secret tokens and allowed IPs, rate limiting, TLS certificate management, and metrics endpoint setup. ```go func webhookSetup() { b, err := bote.New(ctx, token, // Basic webhook setup bote.WithWebhook("https://example.com/webhook", ":8443"), // Security options bote.WithWebhookSecretToken("my-secret-token"), bote.WithWebhookAllowedTelegramIPs(), bote.WithWebhookSecurityHeaders(), // Rate limiting bote.WithWebhookRateLimit(100, 200), // TLS certificate options bote.WithWebhookCertificate("cert.pem", "key.pem", true, true), // Or auto-generate self-signed certificate: bote.WithWebhookGenerateCertificate("./certs"), // Metrics endpoint bote.WithWebhookMetrics(bote.MetricsConfig{ Registry: prometheus.NewRegistry(), }, "/metrics"), ) // Or use full config struct b, err = bote.New(ctx, token, func(opts *bote.Options) { opts.Config.Mode = bote.PollingModeWebhook opts.Config.Webhook = bote.WebhookConfig{ URL: "https://example.com/webhook", Listen: ":8443", MaxConnections: 40, Security: bote.WebhookSecurityConfig{ SecretToken: "secret", StartHTTPS: true, CertFile: "cert.pem", KeyFile: "key.pem", }, RateLimit: bote.WebhookRateLimitConfig{ Enabled: bote.Ptr(true), RequestsPerSecond: 30, BurstSize: 10, }, } }) } ``` -------------------------------- ### Utilize Bote Context for Bot Operations Source: https://github.com/maxbolgarin/bote/blob/main/README.md Provides examples of accessing user data, managing messages, handling callbacks, and persisting custom values within a handler. ```go func myHandler(ctx bote.Context) error { ctx.User().ID() ctx.SendMain(state, "text", keyboard) ctx.SendNotification("info", nil) ctx.SendError("something went wrong") ctx.User().SetValue("key", value) return nil } ``` -------------------------------- ### Add Middleware for Request Processing in Go Source: https://context7.com/maxbolgarin/bote/llms.txt Demonstrates how to add middleware to a Bote bot for user-level and chat-type specific processing. It includes examples for private chat filtering, banning users, and handling specific update types like text messages in groups. ```go func setupMiddleware(b *bote.Bot) { // User-level middleware (private chats only) b.AddUserMiddleware(func(upd *tele.Update, user bote.User) bool { log.Printf("User %d made an action", user.ID()) // Check if user is banned if isBanned(user.ID()) { return false // Drop the update } return true // Continue processing }) // Chat-type middleware for groups b.AddMiddleware(func(upd *tele.Update) bool { // Rate limiting, analytics, etc. return true }, tele.ChatGroup, tele.ChatSuperGroup) // Handle specific endpoints b.Handle(tele.OnText, func(ctx bote.Context) error { if !ctx.IsPrivate() { if ctx.IsMentioned() { return ctx.SendInChat(ctx.ChatID(), 0, "Hello!", nil) } } return nil }) } ``` -------------------------------- ### User State and Values Management in Bote Source: https://context7.com/maxbolgarin/bote/llms.txt Details how to manage persistent user data and states within the Bote framework. This includes retrieving current states, accessing user message history IDs, setting and getting persistent values (like cart items or preferences) stored in a database, deleting values, clearing cache, updating user language, checking if a bot is disabled for a user, and accessing user statistics like last seen time and creation date. ```go func userStateHandler(ctx bote.Context) error { user := ctx.User() // Get current state mainState := user.StateMain() msgState, ok := user.State(msgID) // Get user messages info msgs := user.Messages() mainMsgID := msgs.MainID headMsgID := msgs.HeadID historyIDs := msgs.HistoryIDs // Persistent values (stored in database) user.SetValue("cart", []string{"item1", "item2"}) user.SetValue("preferences", map[string]any{"theme": "dark"}) cart, ok := user.GetValue("cart") if ok { items := cart.([]string) // Use items... } user.DeleteValue("temporary_data") user.ClearCache() // Delete all values // Update user language user.UpdateLanguage("ru") // Check if user disabled the bot if user.IsDisabled() { return nil } // User stats stats := user.Stats() lastSeen := stats.LastSeenTime created := stats.CreatedTime totalActions := stats.NumberOfStateChangesTotal return nil } ``` -------------------------------- ### Enable Privacy Mode for GDPR Compliance in Go Source: https://context7.com/maxbolgarin/bote/llms.txt Configures privacy modes for a Bote bot to comply with GDPR. It shows how to set up low privacy mode (storing only UserID and Username) and strict privacy mode (encrypting all user identifiers) with custom encryption and HMAC keys or key providers. Includes examples of working with encrypted user IDs. ```go func privacySetup() { // Low privacy mode - stores UserID and Username only b, err := bote.New(ctx, token, bote.WithLowPrivacyMode(), ) // Strict privacy mode - encrypts all user identifiers encKey := "hex-encoded-32-byte-encryption-key" hmacKey := "hex-encoded-32-byte-hmac-key" b, err = bote.New(ctx, token, bote.WithStrictPrivacyMode(&encKey, nil, &hmacKey, nil), bote.WithUserDB(myCustomStorage), // Required for strict mode ) // Or with key provider for key rotation support b, err = bote.New(ctx, token, bote.WithStrictPrivacyModeKeyProvider(myKeysProvider), ) // Working with encrypted user IDs fullID := ctx.User().IDFull() // fullID.IDHMAC - HMAC for database lookups // fullID.IDEnc - Encrypted ID for decryption when needed // Decrypt user ID when needed plainID, err := b.GetUserID(fullID) } ``` -------------------------------- ### Configure Bote Bot with Options Struct (Go) Source: https://github.com/maxbolgarin/bote/blob/main/README.md Demonstrates how to initialize a Bote bot using a configuration struct, setting various options like default language, message deletion, logging, user database, and message handlers. This approach allows for detailed customization of the bot's behavior. ```go b, err := bote.New(ctx, token, func(opts *bote.Options) { opts.Config = bote.Config{ Bot: bote.BotConfig{ DefaultLanguage: "en", DeleteMessages: bote.Ptr(true), NoPreview: true, }, Log: bote.LogConfig{ Enable: bote.Ptr(true), LogUpdates: bote.Ptr(true), }, } opts.UserDB = myStorage opts.Msgs = myMessages }) ``` -------------------------------- ### Building Inline Keyboards in Bote Source: https://context7.com/maxbolgarin/bote/llms.txt Illustrates how to construct inline keyboards using the Bote library. It covers automatic row layout based on button count or text length, manual keyboard construction for complex layouts, and the use of callback data for button actions. It also introduces `KeyboardWithContext` for a cleaner API. ```go func keyboardExamples(ctx bote.Context) { // SingleRow - all buttons in one row kb := bote.SingleRow( ctx.Btn("Yes", yesHandler), ctx.Btn("No", noHandler), ) // InlineBuilder - auto-layout with column count and rune type kb = bote.InlineBuilder(2, bote.TwoBytesPerRune, ctx.Btn("Option A", handlerA), ctx.Btn("Option B", handlerB), ctx.Btn("Option C", handlerC), ctx.Btn("Option D", handlerD), ) // Manual Keyboard builder for complex layouts kb2 := bote.NewKeyboard(3) // 3 buttons per row kb2.Add(ctx.Btn("One", h1)) kb2.Add(ctx.Btn("Two", h2)) kb2.StartNewRow() kb2.Add(ctx.Btn("Three", h3)) kb2.AddFooter(ctx.Btn("Back", backHandler)) markup := kb2.CreateInlineMarkup() // Buttons with callback data ctx.Btn("Delete", deleteHandler, userID, itemID) // In handler: ctx.DataParsed() returns []string{userID, itemID} // KeyboardWithContext for cleaner syntax kwc := bote.NewKeyboardWithContext(ctx, 2) kwc.AddBtn("Button 1", handler1) kwc.AddBtn("Button 2", handler2) kwc.ABR("New Row Button", handler3) // AddBtnRow shortcut markup = kwc.CreateInlineMarkup() } // Rune size types for automatic row sizing: // bote.OneBytePerRune - English characters // bote.TwoBytesPerRune - Cyrillic characters // bote.FourBytesPerRune - Emojis and special symbols ``` -------------------------------- ### Configure Bote with Option Functions Source: https://github.com/maxbolgarin/bote/blob/main/README.md Demonstrates how to customize the Bote instance using functional options like custom storage, logging, and default language settings. ```go b, err := bote.New(ctx, token, bote.WithDefaultLanguage("en"), bote.WithLogger(myLogger), bote.WithUserDB(myStorage), bote.WithMsgsProvider(myMessages), bote.WithDebugIncomingUpdates(), ) ``` -------------------------------- ### Configure environment variables Source: https://context7.com/maxbolgarin/bote/llms.txt Lists the environment variables used to configure bot operation modes, webhook settings, and general bot behavior without modifying code. ```bash BOTE_MODE=long BOTE_LP_TIMEOUT=15s BOTE_WEBHOOK_URL=https://example.com/webhook BOTE_WEBHOOK_LISTEN=:8443 BOTE_WEBHOOK_SECRET_TOKEN=mysecret BOTE_WEBHOOK_RATE_LIMIT_RPS=30 BOTE_DEFAULT_LANGUAGE=en BOTE_PARSE_MODE=HTML BOTE_DELETE_MESSAGES=true BOTE_NO_PREVIEW=false BOTE_USER_CACHE_CAPACITY=10000 BOTE_USER_CACHE_TTL=24h ``` -------------------------------- ### Implement User Persistence with UsersStorage (Go) Source: https://github.com/maxbolgarin/bote/blob/main/README.md Details the implementation of the `UsersStorage` interface in Go for persisting user data. This involves defining methods for inserting, finding, and asynchronously updating user models, allowing the Bote bot to maintain user state across restarts. ```go type MyStorage struct { db *sql.DB } func (s *MyStorage) Insert(ctx context.Context, user bote.UserModel) error { // Insert user into database return nil } func (s *MyStorage) Find(ctx context.Context, id bote.FullUserID) (bote.UserModel, bool, error) { // Find user by ID (use id.IDPlain or id.IDHMAC depending on privacy mode) return bote.UserModel{}, false, nil } func (s *MyStorage) UpdateAsync(id bote.FullUserID, diff *bote.UserModelDiff) { // Apply partial update. Bote wraps this with an ordered queue (gorder), // so updates are guaranteed to arrive in order per user. // You can use a simple synchronous DB call here. } b, err := bote.New(ctx, token, bote.WithUserDB(&MyStorage{db: db})) ``` -------------------------------- ### Create Inline Keyboards with Bote (Go) Source: https://github.com/maxbolgarin/bote/blob/main/README.md Shows different methods for creating inline keyboards in Bote. This includes a single-row layout, an auto-layout builder with specified column counts and rune size types, and a manual builder for precise control over button placement. It also covers adding callback data to buttons. ```go // Single row kb := bote.SingleRow( ctx.Btn("Yes", yesHandler), ctx.Btn("No", noHandler), ) // Auto-layout with column count and rune type kb := bote.InlineBuilder(2, bote.TwoBytesPerRune, ctx.Btn("Option A", handlerA), ctx.Btn("Option B", handlerB), ctx.Btn("Option C", handlerC), ctx.Btn("Option D", handlerD), ) // Manual builder kb := bote.NewKeyboard(3) kb.Add(ctx.Btn("One", h1)) kb.Add(ctx.Btn("Two", h2)) kb.StartNewRow() kb.Add(ctx.Btn("Three", h3)) kb.AddFooter(ctx.Btn("Back", backHandler)) markup := kb.CreateInlineMarkup() // Buttons with callback data ctx.Btn("Delete", deleteHandler, userID, itemID) // In handler: ctx.DataParsed() returns []string{userID, itemID} ``` -------------------------------- ### Configure Prometheus metrics in Go Source: https://context7.com/maxbolgarin/bote/llms.txt Shows how to initialize and register Prometheus metrics within the Bote framework to monitor bot performance and health. ```go import "github.com/prometheus/client_golang/prometheus" func metricsSetup() { registry := prometheus.NewRegistry() b, err := bote.New(ctx, token, bote.WithMetricsConfig(bote.MetricsConfig{ Registry: registry, Namespace: "mybot", Subsystem: "telegram", ConstLabels: prometheus.Labels{"env": "production"}, }), ) } ``` -------------------------------- ### Handle Text Input States in Bote (Go) Source: https://github.com/maxbolgarin/bote/blob/main/README.md Illustrates how to implement text input handling for user states in Bote. It covers defining states that expect text input, setting a global text handler, and processing user input based on their current state to update user data and transition to new states. ```go // In your state definition func (s AppState) IsText() bool { return s == StateAwaitingName || s == StateAwaitingEmail } // Set the text handler b.SetTextHandler(func(ctx bote.Context) error { text := ctx.Text() switch ctx.User().StateMain() { case StateAwaitingName: ctx.User().SetValue("name", text) return ctx.EditMain(StateAwaitingEmail, "Now enter your email:", nil) case StateAwaitingEmail: ctx.User().SetValue("email", text) name, _ := ctx.User().GetValue("name") msg := bote.FB("Name: ") + name.(string) + "\n" + bote.FB("Email: ") + text return ctx.EditMain(StateMenu, msg, menuKeyboard(ctx)) default: return ctx.SendNotification("Send /start to begin", nil) } }) // Trigger text input by sending a message with a text state func askNameHandler(ctx bote.Context) error { return ctx.SendMain(StateAwaitingName, "Enter your name:", nil) } ``` -------------------------------- ### Define Custom Bot States Source: https://github.com/maxbolgarin/bote/blob/main/README.md Shows how to implement the State interface to manage application flow and determine if a state expects text input. ```go type AppState string func (s AppState) String() string { return string(s) } func (s AppState) IsText() bool { return s == StateAwaitingInput } func (s AppState) NotChanged() bool { return false } const ( StateMenu AppState = "menu" StateSettings AppState = "settings" StateAwaitingInput AppState = "awaiting_input" ) ``` -------------------------------- ### Configure Bot Restart Recovery with State Map (Go) Source: https://github.com/maxbolgarin/bote/blob/main/README.md Explains how to enable bot restart recovery in Bote by providing a state map. This map links bot states to their corresponding handlers, allowing the bot to rebuild the UI and resume user interactions from where they left off after a restart. ```go stateMap := map[bote.State]bote.InitBundle{ StateMenu: { Handler: menuHandler, }, StateSettings: { Handler: settingsHandler, }, StateAwaitingName: { Handler: askNameHandler, }, } stopCh := b.Start(ctx, startHandler, stateMap) ``` -------------------------------- ### Configure Webhook Mode for Bote (Go) Source: https://github.com/maxbolgarin/bote/blob/main/README.md Shows how to set up Bote to run in webhook mode, receiving updates from Telegram via HTTP POST requests. This configuration includes specifying the webhook URL, port, secret token, rate limiting, and security options. ```go b, err := bote.New(ctx, token, bote.WithWebhook("https://example.com/webhook", ":8443"), bote.WithWebhookSecretToken("my-secret"), bote.WithWebhookRateLimit(100, 200), bote.WithWebhookSecurityHeaders(), bote.WithWebhookAllowedTelegramIPs(), ) ``` -------------------------------- ### Implement Middleware for Bote (Go) Source: https://github.com/maxbolgarin/bote/blob/main/README.md Demonstrates how to add middleware to a Bote application for request processing. This includes user-level middleware for private chats and chat-type middleware for filtering updates based on chat type, enabling features like rate limiting and analytics. ```go // User-level middleware (private chats only) b.AddUserMiddleware(func(upd *tele.Update, user bote.User) bool { log.Printf("User %d made an action", user.ID()) return true // return false to drop the update }) // Chat-type middleware b.AddMiddleware(func(upd *tele.Update) bool { // Rate limiting, analytics, etc. return true }, tele.ChatGroup, tele.ChatSuperGroup) ``` -------------------------------- ### Format Messages with Rich Text and Code Blocks Source: https://github.com/maxbolgarin/bote/blob/main/README.md Provides utility functions for formatting messages with rich text styles like bold, italic, code, preformatted blocks, strikethrough, and underline. It also includes a builder pattern for constructing complex messages programmatically, allowing conditional text additions and line breaks. ```go msg := bote.FB("Bold") + " and " + bote.FI("italic") + "\n" msg += bote.FC("code") + " or " + bote.FP("pre", "go") + "\n" msg += bote.FS("strikethrough") + " " + bote.FU("underline") // Using the builder b := bote.NewBuilder() b.Writeln(bote.FB("User Profile")) b.Writeln("") b.Writeln("Name: " + name) b.Writeln("Email: " + email) b.WriteIf(isAdmin, bote.FB("Admin")) msg = b.String() ``` -------------------------------- ### Define Custom User States for Bote in Go Source: https://context7.com/maxbolgarin/bote/llms.txt Illustrates how to define custom user states in Go by creating a string type that implements the `bote.State` interface. This allows for tracking user flow and handling text inputs within the bot. ```go // Define custom states as a string type implementing State interface type AppState string func (s AppState) String() string { return string(s) } func (s AppState) IsText() bool { return s == StateAwaitingInput || s == StateAwaitingEmail } func (s AppState) NotChanged() bool { return false } const ( StateMenu AppState = "menu" StateSettings AppState = "settings" StateAwaitingInput AppState = "awaiting_input" StateAwaitingEmail AppState = "awaiting_email" ) // Built-in states available: // bote.NoChange - State should not change after Send/Edit // bote.FirstRequest - Initial state for new users // bote.Unknown - Unknown state // bote.Disabled - Disabled user state ``` -------------------------------- ### Integrate Prometheus Metrics for Bot Monitoring Source: https://github.com/maxbolgarin/bote/blob/main/README.md Configures Prometheus metrics for the Bote instance, allowing for detailed monitoring of bot activity. It requires a Prometheus registry to be provided. This enables tracking of various metrics such as updates, handler inflight status, handler duration, errors, messages sent, and user activity. ```go import "github.com/prometheus/client_golang/prometheus" registry := prometheus.NewRegistry() b, err := bote.New(ctx, token, bote.WithMetricsConfig(bote.MetricsConfig{ Registry: registry, }), ) ``` -------------------------------- ### Handle Text Input with User States in Go Source: https://context7.com/maxbolgarin/bote/llms.txt Sets up a global text handler to manage user interactions based on their state. It processes user input for name and email, stores them, and responds with a formatted message. This requires the 'bote' library and context management. ```go func main() { b, _ := bote.New(ctx, token) // Set global text handler b.SetTextHandler(func(ctx bote.Context) error { text := ctx.Text() state := ctx.User().StateMain() switch state { case StateAwaitingName: ctx.User().SetValue("name", text) return ctx.EditMain(StateAwaitingEmail, "Now enter your email:", nil) case StateAwaitingEmail: ctx.User().SetValue("email", text) name, _ := ctx.User().GetValue("name") msg := bote.FB("Name: ") + name.(string) + "\n" + bote.FB("Email: ") + text return ctx.EditMain(StateMenu, msg, menuKeyboard(ctx)) default: return ctx.SendNotification("Send /start to begin", nil) } }) b.Start(ctx, startHandler, stateMap) } // Trigger text input by sending message with text state func askNameHandler(ctx bote.Context) error { return ctx.SendMain(StateAwaitingName, "Enter your name:", nil) } ``` -------------------------------- ### Format HTML messages in Go Source: https://context7.com/maxbolgarin/bote/llms.txt Demonstrates the use of built-in formatting helpers to create styled messages and complex layouts using the Bote message builder. ```go func formattingExamples() string { msg := bote.FB("Bold") + " and " + bote.FI("italic") + "\n" msg += bote.FC("code") + " or " + bote.FP("pre block") + "\n" msg += bote.FS("strikethrough") + " " + bote.FU("underline") msg += bote.FBU("Bold Underline") msg += bote.FBI("Bold Italic") msg += bote.FBC("Bold Code") msg = bote.FBf("Count: %d", 42) msg = bote.FIf("Name: %s", username) safeUsername := bote.EscapeHTML(userInput) msg = bote.FB("User: ") + safeUsername b := bote.NewBuilder() b.Writeln(bote.FB("User Profile")) b.Writeln("") b.Writeln("Name: " + name) b.Writeln("Email: " + email) b.WriteIf(isAdmin, bote.FB("👑 Admin")) b.WritelnIf(hasPremium, "Premium: Yes", "Premium: No") b.Writelnn("Section with double newline") b.Writef("Score: %d points", score) return b.String() } ``` -------------------------------- ### Implement UserStorage interface in Go Source: https://context7.com/maxbolgarin/bote/llms.txt Defines a custom storage implementation for persistent user data using SQL. It provides methods for inserting, finding, updating, and deleting user records within the Bote framework. ```go type MyStorage struct { db *sql.DB } func (s *MyStorage) Insert(ctx context.Context, user bote.UserModel) error { _, err := s.db.ExecContext(ctx, "INSERT INTO users (id, language_code, state, messages, values) VALUES (?, ?, ?, ?, ?)", user.ID.IDPlain, user.LanguageCode, user.State, user.Messages, user.Values) return err } func (s *MyStorage) Find(ctx context.Context, id bote.FullUserID) (bote.UserModel, bool, error) { var user bote.UserModel err := s.db.QueryRowContext(ctx, "SELECT * FROM users WHERE id = ?", id.IDPlain).Scan(&user) if err == sql.ErrNoRows { return bote.UserModel{}, false, nil } return user, err == nil, err } func (s *MyStorage) UpdateAsync(id bote.FullUserID, diff *bote.UserModelDiff) { go func() { if diff.State != nil && diff.State.Main != nil { s.db.Exec("UPDATE users SET state_main = ? WHERE id = ?", *diff.State.Main, id.IDPlain) } }() } func (s *MyStorage) Delete(ctx context.Context, id bote.FullUserID) error { _, err := s.db.ExecContext(ctx, "DELETE FROM users WHERE id = ?", id.IDPlain) return err } b, _ := bote.New(ctx, token, bote.WithUserDB(&MyStorage{db: db})) ``` -------------------------------- ### Create external contexts in Go Source: https://context7.com/maxbolgarin/bote/llms.txt Allows triggering bot handlers programmatically by simulating user interactions like button callbacks or text messages. ```go func externalTrigger(b *bote.Bot) { ctx := bote.NewContext(b, userID, callbackMsgID, "data1", "data2") err := someHandler(ctx) ctx = bote.NewContextText(b, userID, textMsgID, "user input text") err = textHandler(ctx) ctx, err = bote.NewContextSecure(b, encryptedUserID, callbackMsgID, "data") ctx, err = bote.NewContextTextSecure(b, encryptedUserID, textMsgID, "text") } ``` -------------------------------- ### Bote Configuration Options Source: https://context7.com/maxbolgarin/bote/llms.txt Environment variables for configuring Bote's privacy and logging settings. These settings control the bot's security posture and the verbosity of its operational logs. ```env BOTE_PRIVACY_MODE=strict # low or strict BOTE_ENCRYPTION_KEY=hex-32-bytes BOTE_HMAC_KEY=hex-32-bytes # Logging BOTE_LOG_ENABLE=true BOTE_LOG_UPDATES=true BOTE_LOG_LEVEL=info # debug, info, warn, error BOTE_LOG_HIDE_USER_DATA=false ``` -------------------------------- ### Handle Messages in Public Groups and Channels Source: https://github.com/maxbolgarin/bote/blob/main/README.md Extends Bote's functionality to process messages in group chats and public channels, in addition to private chats. It demonstrates how to check if a message is from a private chat and how to respond specifically in group or channel contexts, including mentioning the bot. ```go // Register a handler for text messages in any chat b.Handle(tele.OnText, func(ctx bote.Context) error { if !ctx.IsPrivate() { // Group/channel message if ctx.IsMentioned() { return ctx.SendInChat(ctx.ChatID(), 0, "Hello from the bot!", nil) } return nil } // Private message — handled by text handler return nil }) ``` -------------------------------- ### Send Various Message Types with Bote Context in Go Source: https://context7.com/maxbolgarin/bote/llms.txt Shows how to use the `bote.Context` interface in Go to send different types of messages, including main, head, notification, error, files, and messages to specific chats. Each method handles message lifecycle management automatically. ```go func myHandler(ctx bote.Context) error { // SendMain - sends new main message, old main becomes history err := ctx.SendMain(StateMenu, "Main message text", keyboard) // Send - sends both main and head messages together err = ctx.Send(StateMenu, "Main text", "Head text", mainKb, headKb) // SendNotification - sends notification, auto-deletes old notification err = ctx.SendNotification("Task completed successfully!", nil) // SendError - sends error message with auto-close button err = ctx.SendError("Something went wrong") // SendFile - sends a file to the user err = ctx.SendFile("report.pdf", fileBytes) // SendInChat - sends to a specific chat (groups/channels) msgID, err := ctx.SendInChat(chatID, threadID, "Hello group!", nil) return err } ``` -------------------------------- ### Accessing Context Data in Bote Source: https://context7.com/maxbolgarin/bote/llms.txt Explains how to retrieve various pieces of information from the `bote.Context` object. This includes user details (ID, username, language, state, messages, stats), message specifics (ID, chat ID, type, mention status, reply status), callback button data, text message content, and custom context values. It also shows how to access the underlying `telebot` context. ```go func dataHandler(ctx bote.Context) error { // User information userID := ctx.User().ID() username := ctx.User().Username() language := ctx.User().Language() mainState := ctx.User().StateMain() messages := ctx.User().Messages() stats := ctx.User().Stats() // Message information msgID := ctx.MessageID() chatID := ctx.ChatID() chatType := ctx.ChatType() isPrivate := ctx.IsPrivate() isMentioned := ctx.IsMentioned() isReply := ctx.IsReply() // Callback button data buttonID := ctx.ButtonID() rawData := ctx.Data() // e.g., "a|b|c" parsedData := ctx.DataParsed() // []string{"a", "b", "c"} // Text message data text := ctx.Text() text, textMsgID := ctx.TextWithMessage() // Custom context values (per-request, not persisted) ctx.Set("key", "value") value := ctx.Get("key") // Access underlying telebot context teleCtx := ctx.Tele() return nil } ``` -------------------------------- ### Configure Strict Privacy Mode with AES-256 Encryption Source: https://github.com/maxbolgarin/bote/blob/main/README.md Enables strict privacy mode by encrypting user IDs with AES-256 and storing only HMAC for lookups. This mode ensures no usernames or names are stored, user IDs are encrypted in the database, and logs only show HMAC prefixes. Requires a 32-byte AES key and a 32-byte HMAC key, both hex-encoded. ```go encKey := "hex-encoded-32-byte-key" hmacKey := "hex-encoded-32-byte-key" b, err := bote.New(ctx, token, bote.WithStrictPrivacyMode(&encKey, nil, &hmacKey, nil), ) ``` -------------------------------- ### Edit Messages Using Bote Context in Go Source: https://context7.com/maxbolgarin/bote/llms.txt Demonstrates how to edit existing messages in Go using the `bote.Context` interface. This includes editing main messages, head messages, history messages, and messages within specific chats, while maintaining state management and button handlers. ```go func editHandler(ctx bote.Context) error { // EditMain - edits the current main message err := ctx.EditMain(StateSettings, "Updated main message", newKeyboard) // Edit - edits both main and head messages err = ctx.Edit(StateSettings, "New main", "New head", mainKb, headKb) // EditMainReplyMarkup - edits only the keyboard of main message err = ctx.EditMainReplyMarkup(newKeyboard) // EditHistory - edits a specific history message by ID err = ctx.EditHistory(StateOther, msgID, "Updated history message", kb) // EditHead - edits only the head message err = ctx.EditHead("Updated head text", headKb) // EditInChat - edits message in a specific chat err = ctx.EditInChat(chatID, msgID, "Updated text", kb) return err } ``` -------------------------------- ### Deleting Messages in Bote Source: https://context7.com/maxbolgarin/bote/llms.txt Demonstrates various methods for deleting messages within the Bote framework. This includes deleting the head message, notifications, errors, specific history messages, all messages from a certain ID, messages in a specific chat, and removing users along with their messages. It handles different deletion scenarios and provides error handling. ```go func deleteHandler(ctx bote.Context) error { // DeleteHead - deletes the head message err := ctx.DeleteHead() // DeleteNotification - deletes current notification err = ctx.DeleteNotification() // DeleteError - deletes current error message err = ctx.DeleteError() // DeleteHistory - deletes a specific history message err = ctx.DeleteHistory(msgID) // DeleteAll - deletes all messages from specified ID ctx.DeleteAll(fromMsgID) // DeleteInChat - deletes message in specific chat err = ctx.DeleteInChat(chatID, msgID) // DeleteUser - removes user from DB and deletes all their messages success := ctx.DeleteUser() return err } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.