To receive inline queries, you need to enable inline mode for your bot. Go to @BotFather, select your bot, go to Bot Settings → Inline 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
Copy
type InlineQuery struct {
QueryID int64
Query string
OriginalUpdate *UpdateBotInlineQuery
Sender *UserObj
SenderID int64
Offset string
PeerType InlineQueryPeerType
Client *Client
}
Basic Properties
Unique query identifier
Copy
queryID := q.QueryID
Query text after bot username
Copy
query := q.Query // Text after @bot
Pagination offset for next results
Copy
offset := q.Offset
Type of chat where query is used
Copy
peerType := q.PeerType
User who sent the query
Copy
user := q.Sender
fmt.Println(user.FirstName)
Query Text
Copy
// Get complete query text
text := q.Query
Answer Methods
Basic Answer
Copy
// 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
Copy
// 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
Copy
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
Copy
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
Copy
builder := q.Builder()
builder.Document("document.pdf",
&telegram.ArticleOptions{
Caption: "Document caption",
})
q.Answer(builder.Results())
Special Result Types
Copy
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
Copy
if q.IsPrivate() {
// Query from private chat
}
Pagination
Copy
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
Copy
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
})
Image Gallery
Copy
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
Copy
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
Copy
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 Settings → Inline Feedback and set it to 100%.
Handle Chosen Results
Copy
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
Result ID that was chosen
Copy
resultID := s.ID
Chat where result was sent
Copy
chatID := s.ChatID()
Message ID of sent result
Copy
msgID := s.MessageID()
Complete Example
Copy
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()
}