Request Flow
This document details how Telegram updates flow through Alita Robot, from reception to response.
Update Processing Pipeline
Section titled “Update Processing Pipeline”+-------------+ +----------------+ +------------+ +----------+| Telegram | --> | HTTP/Polling | --> | Dispatcher | --> | Handlers || Bot API | | Receiver | | (Router) | | (Modules)|+-------------+ +----------------+ +------------+ +----------+ | | | v | +------+------+ | | Permission | | | Checks | | +------+------+ | | | v | +------+------+ | | Database | | | / Cache | | +------+------+ | | v v +----------+ +----------+ | Error | | Response | | Handler | | to User | +----------+ +----------+Initialization Sequence
Section titled “Initialization Sequence”When the bot starts (main.go), it performs these steps in order:
-
Health Check Mode Optional
If the
--healthflag is passed, the process performs an HTTP GET to/healthand exits with the status code. This is used by Docker health checks.if os.Args[1] == "--health" {// HTTP GET to /health, exit with status codeos.Exit(0)} -
Version Check Optional
If the
--version,-version, or-vflag is passed, the process prints the bot version and exits immediately without initializing any services.if os.Args[1] == "--version" || os.Args[1] == "-version" || os.Args[1] == "-v" {fmt.Println(config.AppConfig.BotVersion)os.Exit(0)} -
Panic Recovery Setup Safety
A top-level deferred recovery ensures the process logs the panic and exits cleanly rather than crashing silently.
defer func() {if r := recover(); r != nil {log.Errorf("[Main] Panic recovered: %v", r)os.Exit(1)}}() -
Cache Initialization Infrastructure
The Redis cache is initialized with connection retry logic (exponential backoff). Cache must be available before i18n (which uses it for translation caching) and before the database layer.
if err := cache.InitCache(); err != nil {log.Fatalf("Failed to initialize cache: %v", err)} -
Locale Manager Initialization i18n
The singleton
LocaleManagerloads embedded YAML translation files for all supported languages.localeManager := i18n.GetManager()localeManager.Initialize(&Locales, "locales", i18n.DefaultManagerConfig()) -
OpenTelemetry Tracing Initialization Observability
Sets up distributed tracing with OTLP or console exporters based on environment configuration (
OTEL_EXPORTER_OTLP_ENDPOINT,OTEL_SERVICE_NAME,OTEL_TRACES_SAMPLE_RATE).tracing.InitTracing() -
HTTP Transport Configuration Networking
Connection pooling is configured for outbound HTTP requests to the Telegram API.
httpTransport := &http.Transport{MaxIdleConns: config.AppConfig.HTTPMaxIdleConns,MaxIdleConnsPerHost: config.AppConfig.HTTPMaxIdleConnsPerHost,IdleConnTimeout: 120 * time.Second,ForceAttemptHTTP2: true,} -
Bot Client Creation Core
The gotgbot client is initialized with the configured HTTP transport and a 30-second timeout.
b, err := gotgbot.NewBot(config.AppConfig.BotToken, &gotgbot.BotOpts{BotClient: &gotgbot.BaseBotClient{Client: http.Client{Transport: transport, Timeout: 30 * time.Second},},}) -
Connection Pre-warming Performance
Three
GetMecalls run in a background goroutine to establish the HTTP connection pool before real traffic arrives.go func() {for i := 0; i < 3; i++ {b.GetMe(nil) // Establish connection pooltime.Sleep(100 * time.Millisecond)}}()Pre-warming prevents the first real user request from paying the TCP + TLS handshake cost. The 3 calls ensure multiple connections are established in the pool.
-
Initial Checks Validation
Validates configuration, initializes cache, and performs startup health checks.
alita.InitialChecks(b) // Validates config, initializes cache -
Async Processor Optional
If
EnableAsyncProcessingis configured, the async processor is initialized for non-critical background operations.if config.AppConfig.EnableAsyncProcessing {async.InitializeAsyncProcessor()} -
Dispatcher Creation Core
The dispatcher routes updates to handlers with bounded concurrency. It uses a
TracingProcessorwrapper for trace context propagation in polling mode.dispatcher := ext.NewDispatcher(&ext.DispatcherOpts{Error: errorHandler,MaxRoutines: config.AppConfig.DispatcherMaxRoutines,}) -
Monitoring Systems Observability
Three monitoring subsystems start: background stats collection (every 30s), auto-remediation (GC triggers on memory thresholds), and activity monitoring (per-chat and per-user tracking).
statsCollector = monitoring.NewBackgroundStatsCollector()autoRemediation = monitoring.NewAutoRemediationManager(statsCollector)activityMonitor = monitoring.NewActivityMonitor() -
HTTP Server & Mode Selection Core
The unified HTTP server registers health, metrics, and optionally pprof endpoints. Then either webhook or polling mode is activated.
httpServer := httpserver.New(config.AppConfig.HTTPPort)httpServer.RegisterHealth()httpServer.RegisterMetrics()if config.AppConfig.UseWebhooks {httpServer.RegisterWebhook(b, dispatcher, secret, domain)} else {updater.StartPolling(b, pollingOpts)}
Module Loading Order
Section titled “Module Loading Order”After dispatcher creation, modules are loaded via alita/main.go:
func LoadModules(dispatcher *ext.Dispatcher) { // Initialize help system first modules.HelpModule.AbleMap.Init()
// Load help LAST (deferred) to collect all commands defer modules.LoadHelp(dispatcher)
// Core modules (order matters for handler priority) modules.LoadBotUpdates(dispatcher) // Bot status tracking modules.LoadAntispam(dispatcher) // Spam protection modules.LoadLanguage(dispatcher) // Language settings modules.LoadAdmin(dispatcher) // Admin commands modules.LoadPin(dispatcher) // Pin management modules.LoadMisc(dispatcher) // Misc utilities modules.LoadBans(dispatcher) // Ban/kick commands modules.LoadMutes(dispatcher) // Mute commands modules.LoadPurges(dispatcher) // Message purging modules.LoadUsers(dispatcher) // User tracking modules.LoadReports(dispatcher) // Report system modules.LoadDev(dispatcher) // Developer tools modules.LoadLocks(dispatcher) // Chat locks modules.LoadFilters(dispatcher) // Message filters modules.LoadAntiflood(dispatcher) // Flood protection modules.LoadNotes(dispatcher) // Notes system modules.LoadConnections(dispatcher) // Chat connections modules.LoadDisabling(dispatcher) // Command disabling modules.LoadRules(dispatcher) // Rules management modules.LoadWarns(dispatcher) // Warning system modules.LoadGreetings(dispatcher) // Welcome messages modules.LoadCaptcha(dispatcher) // CAPTCHA verification modules.LoadBlacklists(dispatcher) // Blacklist system modules.LoadBackup(dispatcher) // Backup/export commands (load last)}Handler Registration Pattern
Section titled “Handler Registration Pattern”Each module registers handlers using gotgbot’s handler system:
func LoadBans(dispatcher *ext.Dispatcher) { // Register module in help system HelpModule.AbleMap.Store(bansModule.moduleName, true)
// Command handlers dispatcher.AddHandler(handlers.NewCommand("ban", bansModule.ban)) dispatcher.AddHandler(handlers.NewCommand("kick", bansModule.kick)) dispatcher.AddHandler(handlers.NewCommand("unban", bansModule.unban))
// Callback query handlers dispatcher.AddHandler(handlers.NewCallback( callbackquery.Prefix("restrict."), bansModule.restrictButtonHandler, ))}Handler Types
Section titled “Handler Types”| Type | Registration | Trigger |
|---|---|---|
| Command | handlers.NewCommand("cmd", fn) | /cmd messages |
| Callback | handlers.NewCallback(filter, fn) | Button presses |
| Message | handlers.NewMessage(filter, fn) | Text messages |
| ChatMember | handlers.NewChatMemberUpdated(filter, fn) | Member updates |
Handler Groups
Section titled “Handler Groups”Handlers can be assigned to groups for priority control:
// Negative group = higher priority (runs first)dispatcher.AddHandlerToGroup(handler, -10)
// Group 0 = defaultdispatcher.AddHandler(handler) // Same as group 0
// Positive group = lower prioritydispatcher.AddHandlerToGroup(handler, 10)Permission Check Flow
Section titled “Permission Check Flow”Most admin commands follow this permission checking pattern:
func (m moduleStruct) ban(b *gotgbot.Bot, ctx *ext.Context) error { chat := ctx.EffectiveChat user := ctx.EffectiveSender.User msg := ctx.EffectiveMessage
// 1. Require group chat (not private) if !chat_status.RequireGroup(b, ctx, nil, false) { return ext.EndGroups }
// 2. Require user to be admin if !chat_status.RequireUserAdmin(b, ctx, nil, user.Id, false) { return ext.EndGroups }
// 3. Require bot to be admin if !chat_status.RequireBotAdmin(b, ctx, nil, false) { return ext.EndGroups }
// 4. Check specific permission (restrict members) if !chat_status.CanUserRestrict(b, ctx, nil, user.Id, false) { return ext.EndGroups }
// 5. Check bot has same permission if !chat_status.CanBotRestrict(b, ctx, nil, false) { return ext.EndGroups }
// Proceed with ban logic...}Permission Functions Reference
Section titled “Permission Functions Reference”| Function | Purpose | When to Use |
|---|---|---|
RequireGroup | Ensures chat is group/supergroup | Group-only commands |
RequirePrivate | Ensures chat is private | PM-only commands |
RequireUserAdmin | User must be admin | Admin commands |
RequireBotAdmin | Bot must be admin | Commands needing bot admin |
RequireUserOwner | User must be creator | Owner-only commands |
CanUserRestrict | User can ban/mute | Ban/mute commands |
CanBotRestrict | Bot can ban/mute | Ban/mute commands |
CanUserDelete | User can delete messages | Purge commands |
CanBotDelete | Bot can delete messages | Purge commands |
CanUserPin | User can pin messages | Pin commands |
CanBotPin | Bot can pin messages | Pin commands |
CanUserPromote | User can promote/demote | Admin management |
CanBotPromote | Bot can promote/demote | Admin management |
IsUserAdmin | Check if user is admin | Conditional logic |
IsUserInChat | Check if user is member | User validation |
IsUserBanProtected | Check if user is protected | Before ban/kick |
Response Patterns
Section titled “Response Patterns”Handler Return Values
Section titled “Handler Return Values”// Stop processing, no more handlers runreturn ext.EndGroups
// Continue to subsequent handler groupsreturn ext.ContinueGroups
// Error propagates to dispatcher error handlerreturn errResponse Actions
Section titled “Response Actions”// Reply to the triggering messagemsg.Reply(b, "Response text", &gotgbot.SendMessageOpts{ ParseMode: helpers.HTML,})
// Send new message to chatb.SendMessage(chat.Id, "Message text", nil)
// Edit existing messagemsg.EditText(b, "New text", nil)
// Delete messagemsg.Delete(b, nil)
// Answer callback queryquery.Answer(b, &gotgbot.AnswerCallbackQueryOpts{ Text: "Notification text",})Async Processing
Section titled “Async Processing”Non-critical operations can be processed asynchronously:
// Fire and forget (with panic recovery)go func() { defer func() { if r := recover(); r != nil { log.Error("Panic in async operation") } }()
// Async work here}()
// With timeout protectiongo func() { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel()
select { case <-time.After(2 * time.Second): // Do delayed work case <-ctx.Done(): log.Warn("Operation timed out") }}()Error Handling in Request Flow
Section titled “Error Handling in Request Flow”Dispatcher Error Handler
Section titled “Dispatcher Error Handler”Error: func(b *gotgbot.Bot, ctx *ext.Context, err error) ext.DispatcherAction { // 1. Recover from panics defer error_handling.RecoverFromPanic("DispatcherErrorHandler", "Main")
// 2. Extract context for logging logFields := log.Fields{ "update_id": ctx.UpdateId, "error_type": fmt.Sprintf("%T", err), }
// 3. Check for expected/suppressible errors if helpers.IsExpectedTelegramError(err) { log.WithFields(logFields).Warn("Expected Telegram API error") return ext.DispatcherActionNoop }
// 4. Log the error log.WithFields(logFields).Error("Handler error")
// 5. Continue processing other updates return ext.DispatcherActionNoop}Common Error Patterns
Section titled “Common Error Patterns”// Log and return error (propagates to dispatcher)if err != nil { log.Error(err) return err}
// Log but continue (non-fatal)if err != nil { log.Warn("Non-fatal error:", err)}
// Silent failure for expected cases_, _ = msg.Delete(b, nil) // Ignore delete errorsNext Steps
Section titled “Next Steps”- Module Pattern - Creating new feature modules
- Caching - Redis cache integration
- Project Structure - File organization