Skip to main content
To use inline buttons with callback data, you need to enable inline mode for your bot. Go to @BotFather, select your bot, go to Bot SettingsInline Mode and turn it on.

Overview

CallbackQuery represents a callback from an inline button click. It’s triggered when users click inline keyboard buttons with callback data.

Structure

type CallbackQuery struct {
    QueryID        int64
    Data           []byte
    OriginalUpdate *UpdateBotCallbackQuery
    Sender         *UserObj
    MessageID      int32
    SenderID       int64
    ChatID         int64
    Chat           *ChatObj
    Channel        *Channel
    Peer           Peer
    Client         *Client
}

Basic Properties

Query Information

QueryID
int64
Unique query identifier
queryID := c.QueryID
Data
[]byte
Callback data from button
data := c.Data
DataString()
string
Get callback data as string
dataStr := c.DataString()
MessageID
int32
ID of message with the button
msgID := c.MessageID

Sender Information

GetSenderID()
int64
Get user ID who clicked button
userID := c.GetSenderID()
GetSender()
(*UserObj, error)
Get full sender object
sender, err := c.GetSender()
fmt.Println(sender.FirstName)

Chat Information

GetChatID()
int64
Get chat/channel ID
chatID := c.GetChatID()
ChatType()
string
Get chat type: user, chat, channel
if c.ChatType() == telegram.EntityUser {
    // Private chat
}

Answer Callback

Basic Answer

// Answer with popup message
c.Answer("Button clicked!", &telegram.CallbackOptions{
    Alert: false, // Toast notification
})

Response Methods

Edit Message

  • Edit Text
  • Edit Markup
  • Remove Markup
// Edit message text
c.Edit("Button was clicked!")

// Edit with options
keyboard := telegram.NewKeyboard()
keyboard.AddRow(telegram.Button.Data("New Button", "new_data"))

c.Edit("Updated text", &telegram.SendOptions{
    ParseMode: "HTML",
    ReplyMarkup: keyboard,
})

Send Messages

// Reply to the message with button
msg, err := c.Reply("Replying to your click")

Message Operations

Get Message

// Get the message that has the button
msg, err := c.GetMessage()
if err == nil {
    fmt.Println("Message text:", msg.Text())
}

Delete Message

// Delete message with button
affected, err := c.Delete()
if err == nil {
    fmt.Println("Message deleted")
}

Forward Message

// Forward message to another chat
msg, err := c.ForwardTo(targetChatID, &telegram.ForwardOptions{
    Silent: true,
})

Chat Type Checks

  • Private
  • Group
  • Channel
if c.IsPrivate() {
    c.Answer("Private chat callback")
}

Advanced Features

Conversations

// Start conversation after callback
response, err := c.Ask("What's your name?")
if err == nil {
    c.Respond("Hello, " + response.Text())
}
// Get chat object
chat, err := c.GetChat()

// Get channel object
channel, err := c.GetChannel()

// Get sender user
sender, err := c.GetSender()

Practical Examples

Button Navigation

client.On("callback", func(c *telegram.CallbackQuery) error {
    data := c.DataString()
    
    switch data {
    case "menu_main":
        keyboard := telegram.NewKeyboard()
        keyboard.AddRow(
            telegram.Button.Data("📝 Help", "menu_help"),
            telegram.Button.Data("ℹ️ About", "menu_about"),
        )
        
        c.Edit("Main Menu", &telegram.SendOptions{
            ReplyMarkup: keyboard,
        })
        c.Answer("Main menu opened")
        
    case "menu_help":
        keyboard := telegram.NewKeyboard()
        keyboard.AddRow(telegram.Button.Data("« Back", "menu_main"))
        
        c.Edit("Help Section\n\nCommands:\n/start\n/help", 
            &telegram.SendOptions{
                ReplyMarkup: keyboard,
            })
        c.Answer("Help")
        
    case "menu_about":
        keyboard := telegram.NewKeyboard()
        keyboard.AddRow(telegram.Button.Data("« Back", "menu_main"))
        
        c.Edit("About Bot\n\nVersion 1.0", &telegram.SendOptions{
            ReplyMarkup: keyboard,
        })
        c.Answer("About")
    }
    
    return nil
})

Confirmation Dialog

client.On("callback:delete_", func(c *telegram.CallbackQuery) error {
    data := c.DataString()
    
    if data == "delete_confirm" {
        c.Delete()
        c.Answer("Message deleted!", &telegram.CallbackOptions{
            Alert: true,
        })
    } else if data == "delete_cancel" {
        c.Edit("Deletion cancelled")
        c.Answer("Cancelled")
    }
    
    return nil
})

// Initial message with confirmation
client.On("cmd:delete", func(m *telegram.NewMessage) error {
    keyboard := telegram.NewKeyboard()
    keyboard.AddRow(
        telegram.Button.Data("✅ Yes", "delete_confirm"),
        telegram.Button.Data("❌ No", "delete_cancel"),
    )
    
    m.Reply("Are you sure?", telegram.SendOptions{
        ReplyMarkup: keyboard,
    })
    return nil
})

Pagination

client.On("callback:page_", func(c *telegram.CallbackQuery) error {
    data := c.DataString()
    page := 1
    
    // Parse page number from data
    fmt.Sscanf(data, "page_%d", &page)
    
    // Get items for page
    items := getItemsForPage(page)
    
    // Build message
    text := fmt.Sprintf("Page %d\n\n%s", page, items)
    
    // Build pagination buttons
    keyboard := telegram.NewKeyboard()
    
    row := []telegram.Button{}
    if page > 1 {
        row = append(row, telegram.Button.Data("« Prev", fmt.Sprintf("page_%d", page-1)))
    }
    row = append(row, telegram.Button.Data(fmt.Sprintf(%d ·", page), "page_current"))
    row = append(row, telegram.Button.Data("Next »", fmt.Sprintf("page_%d", page+1)))
    
    keyboard.Row(row...)
    
    c.Edit(text, &telegram.SendOptions{
        ReplyMarkup: keyboard,
    })
    c.Answer(fmt.Sprintf("Page %d", page))
    
    return nil
})

Admin Actions

adminIDs := []int64{123456789, 987654321}

client.On("callback:admin_", func(c *telegram.CallbackQuery) error {
    // Check if user is admin
    isAdmin := false
    for _, id := range adminIDs {
        if c.GetSenderID() == id {
            isAdmin = true
            break
        }
    }
    
    if !isAdmin {
        c.Answer("Access denied!", &telegram.CallbackOptions{
            Alert: true,
        })
        return nil
    }
    
    data := c.DataString()
    
    switch data {
    case "admin_ban":
        // Ban user
        c.Answer("User banned", &telegram.CallbackOptions{
            Alert: true,
        })
        
    case "admin_delete":
        // Delete message
        c.Delete()
        c.Answer("Deleted")
        
    case "admin_warn":
        // Warn user
        c.Answer("User warned", &telegram.CallbackOptions{
            Alert: true,
        })
    }
    
    return nil
})

Loading States

client.On("callback:process", func(c *telegram.CallbackQuery) error {
    // Show loading
    c.Edit("Processing... ⏳")
    c.Answer("Please wait...")
    
    // Do some work
    time.Sleep(2 * time.Second)
    
    // Show result
    keyboard := telegram.NewKeyboard()
    keyboard.AddRow(telegram.Button.Data("Do Again", "process"))
    
    c.Edit("✅ Complete!", &telegram.SendOptions{
        ReplyMarkup: keyboard,
    })
    c.Answer("Done!")
    
    return nil
})

Data with Parameters

client.On("callback:action_", func(c *telegram.CallbackQuery) error {
    data := c.DataString()
    
    // Parse action and parameter
    // Format: "action_TYPE_PARAM"
    parts := strings.Split(data, "_")
    if len(parts) < 3 {
        return nil
    }
    
    action := parts[1]
    param := parts[2]
    
    switch action {
    case "like":
        c.Answer(fmt.Sprintf("Liked item %s", param))
        
    case "share":
        c.Answer(fmt.Sprintf("Shared item %s", param))
        
    case "delete":
        c.Answer(fmt.Sprintf("Deleted item %s", param), 
            &telegram.CallbackOptions{Alert: true})
    }
    
    return nil
})

Complete Example

package main

import (
    "fmt"
    "github.com/amarnathcjd/gogram/telegram"
)

func main() {
    client, _ := telegram.NewClient(telegram.ClientConfig{
        AppID: 6, AppHash: "app_hash",
    })
    
    client.LoginBot("bot_token")
    
    // Send button
    client.On("cmd:start", func(m *telegram.NewMessage) error {
        keyboard := telegram.NewKeyboard()
        keyboard.AddRow(
            telegram.Button.Data("👍 Like", "action_like"),
            telegram.Button.Data("❤️ Love", "action_love"),
        )
        keyboard.AddRow(
            telegram.Button.Data("ℹ️ Info", "action_info"),
        )
        
        m.Reply("Welcome! Click a button:", telegram.SendOptions{
            ReplyMarkup: keyboard,
        })
        return nil
    })
    
    // Handle callbacks
    client.On("callback", func(c *telegram.CallbackQuery) error {
        data := c.DataString()
        sender, _ := c.GetSender()
        
        fmt.Printf("Callback from %s: %s\n", 
            sender.FirstName, data)
        
        switch data {
        case "action_like":
            c.Answer("You clicked Like! 👍")
            c.Edit("You liked this message! 👍")
            
        case "action_love":
            c.Answer("You clicked Love! ❤️", 
                &telegram.CallbackOptions{Alert: true})
            c.Edit("You loved this message! ❤️")
            
        case "action_info":
            keyboard := telegram.NewKeyboard()
            keyboard.AddRow(telegram.Button.Data("« Back", "action_back"))
            
            c.Edit("Bot Info\n\nVersion 1.0\nBy @YourBot", 
                &telegram.SendOptions{
                    ReplyMarkup: keyboard,
                })
            c.Answer("Info")
            
        case "action_back":
            keyboard := telegram.NewKeyboard()
            keyboard.AddRow(
                telegram.Button.Data("👍 Like", "action_like"),
                telegram.Button.Data("❤️ Love", "action_love"),
            )
            keyboard.AddRow(
                telegram.Button.Data("ℹ️ Info", "action_info"),
            )
            
            c.Edit("Welcome! Click a button:", telegram.SendOptions{
                ReplyMarkup: keyboard,
            })
            c.Answer("Main menu")
        }
        
        return nil
    })
    
    client.Idle()
}

Next Steps