package main type Update struct { UpdateID int64 `json:"update_id"` Message *Message `json:"message,omitempty"` EditedMessage *Message `json:"edited_message,omitempty"` CallbackQuery *CallbackQuery `json:"callback_query,omitempty"` } type Message struct { MessageID int64 `json:"message_id"` From *User `json:"from,omitempty"` Chat Chat `json:"chat"` Date int64 `json:"date,omitempty"` Text string `json:"text,omitempty"` } type Chat struct { ID int64 `json:"id"` Type string `json:"type,omitempty"` } type User struct { ID int64 `json:"id"` IsBot bool `json:"is_bot,omitempty"` Username string `json:"username,omitempty"` FirstName string `json:"first_name,omitempty"` } type CallbackQuery struct { ID string `json:"id"` From *User `json:"from,omitempty"` Message *Message `json:"message,omitempty"` Data string `json:"data,omitempty"` } func (u Update) ChatID() (int64, bool) { switch { case u.Message != nil: return u.Message.Chat.ID, true case u.EditedMessage != nil: return u.EditedMessage.Chat.ID, true case u.CallbackQuery != nil && u.CallbackQuery.Message != nil: return u.CallbackQuery.Message.Chat.ID, true } return 0, false } // UserID extracts the Telegram user ID (`from.id`) from whichever sub-payload // is set. Used by the auth layer (factory bot session, requireAuth gate, allowlist). // See factory/doc/adr/20260509-telegram-gateway-auth.md. func (u Update) UserID() (int64, bool) { switch { case u.Message != nil && u.Message.From != nil: return u.Message.From.ID, true case u.EditedMessage != nil && u.EditedMessage.From != nil: return u.EditedMessage.From.ID, true case u.CallbackQuery != nil && u.CallbackQuery.From != nil: return u.CallbackQuery.From.ID, true } return 0, false } func (u Update) Text() string { switch { case u.Message != nil: return u.Message.Text case u.EditedMessage != nil: return u.EditedMessage.Text case u.CallbackQuery != nil: return u.CallbackQuery.Data } return "" }