Skip to main content
To receive inline queries, 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

InlineQuery represents an inline query when users type @yourbot query in any chat. It allows bots to provide results that can be sent to any chat.

Structure

type InlineQuery struct {
    QueryID        int64
    Query          string
    OriginalUpdate *UpdateBotInlineQuery
    Sender         *UserObj
    SenderID       int64
    Offset         string
    PeerType       InlineQueryPeerType
    Client         *Client
}

Basic Properties

QueryID
int64
Unique query identifier
queryID := q.QueryID
Query
string
Query text after bot username
query := q.Query // Text after @bot
Offset
string
Pagination offset for next results
offset := q.Offset
PeerType
InlineQueryPeerType
Type of chat where query is used
peerType := q.PeerType
Sender
*UserObj
User who sent the query
user := q.Sender
fmt.Println(user.FirstName)

Query Text

// Get complete query text
text := q.Query

Answer Methods

Basic Answer

// Answer with results
results := []telegram.InputBotInlineResult{
    // ... result items
}

success, err := q.Answer(results, telegram.InlineSendOptions{
    CacheTime: 300, // Cache for 5 minutes
    Private:   true, // Results specific to user
})

Using Builder

// Use builder for easier result creation
builder := q.Builder()

// Add article
builder.Article("Title", "Description", "Message text")

// Add photo
builder.Photo("https://example.com/photo.jpg")

// Add document
builder.Document("file.pdf")

// Send all results
q.Answer(builder.Results())

Result Types

Article Results

  • Basic Article
  • With Options
  • With Thumbnail
builder := q.Builder()

builder.Article(
    "Result Title",
    "Result description",
    "Message text when selected",
)

q.Answer(builder.Results())

Photo Results

  • From URL
  • From File
  • With Buttons
builder := q.Builder()

builder.Photo("https://example.com/photo.jpg", 
    &telegram.ArticleOptions{
        Caption: "Photo caption",
    })

q.Answer(builder.Results())

Document Results

  • Basic Document
  • With Details
  • Force Document
builder := q.Builder()

builder.Document("document.pdf", 
    &telegram.ArticleOptions{
        Caption: "Document caption",
    })

q.Answer(builder.Results())

Special Result Types

builder := q.Builder()

builder.Article(
    "My Location",
    "Share location",
    "",
    &telegram.ArticleOptions{
        Location: &telegram.InputBotInlineMessageMediaGeo{
            GeoPoint: &telegram.InputGeoPointObj{
                Lat:  40.7128,
                Long: -74.0060,
            },
        },
    },
)

Chat Type Checks

  • Private
  • Group
  • Channel
if q.IsPrivate() {
    // Query from private chat
}

Pagination

client.On("inline", func(q *telegram.InlineQuery) error {
    builder := q.Builder()
    
    // Parse offset
    offset := 0
    if q.Offset != "" {
        fmt.Sscanf(q.Offset, "%d", &offset)
    }
    
    // Get results for this page
    pageSize := 50
    results := getResults(offset, pageSize)
    
    for _, result := range results {
        builder.Article(
            result.Title,
            result.Description,
            result.Text,
        )
    }
    
    // Set next offset
    nextOffset := ""
    if len(results) == pageSize {
        nextOffset = fmt.Sprintf("%d", offset+pageSize)
    }
    
    q.Answer(builder.Results(), telegram.InlineSendOptions{
        NextOffset: nextOffset,
    })
    
    return nil
})

Practical Examples

Search Results

client.On("inline", func(q *telegram.InlineQuery) error {
    query := q.Query
    builder := q.Builder()
    
    if query == "" {
        // Default results
        builder.Article(
            "Search",
            "Type to search",
            "No query provided",
        )
    } else {
        // Search database/API
        results := searchDatabase(query)
        
        for i, result := range results {
            builder.Article(
                result.Title,
                result.Snippet,
                result.FullText,
                &telegram.ArticleOptions{
                    ID:        fmt.Sprintf("result_%d", i),
                    ParseMode: "HTML",
                },
            )
        }
        
        if len(results) == 0 {
            builder.Article(
                "No Results",
                "Try a different query",
                "No results found for: " + query,
            )
        }
    }
    
    q.Answer(builder.Results(), telegram.InlineSendOptions{
        CacheTime: 60, // Cache for 1 minute
    })
    
    return nil
})
client.On("inline", func(q *telegram.InlineQuery) error {
    builder := q.Builder()
    
    images := []struct {
        URL     string
        Caption string
    }{
        {"https://example.com/1.jpg", "Image 1"},
        {"https://example.com/2.jpg", "Image 2"},
        {"https://example.com/3.jpg", "Image 3"},
    }
    
    for i, img := range images {
        keyboard := telegram.NewKeyboard()
        keyboard.AddRow(telegram.Button.URL("View Full", img.URL))
        
        builder.Photo(img.URL, &telegram.ArticleOptions{
            ID:      fmt.Sprintf("img_%d", i),
            Caption: img.Caption,
            ReplyMarkup: keyboard,
        })
    }
    
    q.Answer(builder.Results())
    return nil
})

Dynamic Content

client.On("inline", func(q *telegram.InlineQuery) error {
    builder := q.Builder()
    query := q.Query
    
    // Parse command from query
    parts := strings.Fields(query)
    if len(parts) == 0 {
        builder.Article("Commands", "Available commands", 
            "/weather\n/news\n/quote")
        q.Answer(builder.Results())
        return nil
    }
    
    command := parts[0]
    args := q.Args()
    
    switch command {
    case "/weather":
        weather := getWeather(args)
        builder.Article(
            "Weather",
            args,
            weather,
            &telegram.ArticleOptions{
                ParseMode: "HTML",
            },
        )
        
    case "/news":
        news := getNews(args)
        for i, article := range news {
            builder.Article(
                article.Title,
                article.Source,
                article.Content,
                &telegram.ArticleOptions{
                    ID: fmt.Sprintf("news_%d", i),
                    Thumb: telegram.InputWebDocument{
                        URL: article.ImageURL,
                    },
                },
            )
        }
        
    case "/quote":
        quote := getRandomQuote()
        builder.Article(
            "Random Quote",
            quote.Author,
            quote.Text,
        )
    }
    
    q.Answer(builder.Results())
    return nil
})

User-Specific Results

client.On("inline", func(q *telegram.InlineQuery) error {
    builder := q.Builder()
    userID := q.SenderID
    
    // Get user-specific data
    userData := getUserData(userID)
    
    for _, item := range userData.SavedItems {
        builder.Article(
            item.Title,
            item.Description,
            item.Content,
            &telegram.ArticleOptions{
                ID: item.ID,
            },
        )
    }
    
    // Results are private to this user
    q.Answer(builder.Results(), telegram.InlineSendOptions{
        Private:   true,
        CacheTime: 0, // Don't cache
    })
    
    return nil
})

InlineSend (Chosen Result)

To receive chosen inline result updates, you need to enable inline feedback for your bot. Go to @BotFather, select your bot, go to Bot SettingsInline Feedback and set it to 100%.

Handle Chosen Results

client.On("choseninline", func(s *telegram.InlineSend) error {
    fmt.Printf("User chose result: %s\n", s.ID)
    
    // Get the message
    msg, err := s.GetMessage()
    if err == nil {
        fmt.Printf("Sent to chat: %d\n", msg.ChatID())
    }
    
    // Edit the sent message
    s.Edit("Updated content")
    
    return nil
})

InlineSend Properties

ID
string
Result ID that was chosen
resultID := s.ID
ChatID()
int64
Chat where result was sent
chatID := s.ChatID()
MessageID()
int32
Message ID of sent result
msgID := s.MessageID()

Complete Example

package main

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

func main() {
    client, _ := telegram.NewClient(telegram.ClientConfig{
        AppID: 6, AppHash: "app_hash",
    })
    
    client.LoginBot("bot_token")
    
    // Handle inline queries
    client.On("inline", func(q *telegram.InlineQuery) error {
        builder := q.Builder()
        query := strings.ToLower(q.Query)
        
        if query == "" {
            // Show help
            builder.Article(
                "How to use",
                "Type a query to search",
                "Examples:\n• weather London\n• news tech\n• image cat",
            )
        } else if strings.HasPrefix(query, "weather ") {
            city := strings.TrimPrefix(query, "weather ")
            builder.Article(
                "Weather in " + city,
                "Current conditions",
                fmt.Sprintf("Temperature: 20°C\nCondition: Sunny"),
                &telegram.ArticleOptions{
                    ParseMode: "HTML",
                },
            )
        } else if strings.HasPrefix(query, "image ") {
            keyword := strings.TrimPrefix(query, "image ")
            
            // Mock image results
            for i := 1; i <= 5; i++ {
                builder.Photo(
                    fmt.Sprintf("https://picsum.photos/400/300?random=%d", i),
                    &telegram.ArticleOptions{
                        Caption: fmt.Sprintf("%s #%d", keyword, i),
                    },
                )
            }
        } else {
            // Generic search
            builder.Article(
                "Result 1",
                "First result for: " + query,
                "Content for " + query,
            )
            builder.Article(
                "Result 2",
                "Second result",
                "More content here",
            )
        }
        
        q.Answer(builder.Results(), telegram.InlineSendOptions{
            CacheTime: 300,
        })
        
        return nil
    })
    
    // Handle chosen results
    client.On("choseninline", func(s *telegram.InlineSend) error {
        fmt.Printf("User chose: %s in chat %d\n", s.ID, s.ChatID())
        return nil
    })
    
    client.Idle()
}

Next Steps