Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Inline Mode

Inline mode lets users type @yourbot query in any chat — the bot responds with a list of results the user can tap to send.

Enable inline mode

In @BotFather:

  1. Send /mybots → select your bot
  2. Bot SettingsInline ModeTurn on

Handling inline queries

#![allow(unused)]
fn main() {
Update::InlineQuery(iq) => {
    let query  = iq.query().to_string();
    let qid    = iq.query_id;

    let results = build_results(&query);

    client.answer_inline_query(
        qid,
        results,
        300,   // cache_time in seconds
        false, // is_personal (true = don't share cache across users)
        None,  // next_offset (for pagination)
    ).await?;
}
}

Building results

Article result (text message)

#![allow(unused)]
fn main() {
fn article(id: &str, title: &str, description: &str, text: &str)
    -> tl::enums::InputBotInlineResult
{
    tl::enums::InputBotInlineResult::InputBotInlineResult(
        tl::types::InputBotInlineResult {
            id:          id.into(),
            r#type:      "article".into(),
            title:       Some(title.into()),
            description: Some(description.into()),
            url:         None,
            thumb:       None,
            content:     None,
            send_message: tl::enums::InputBotInlineMessage::Text(
                tl::types::InputBotInlineMessageText {
                    no_webpage:   false,
                    invert_media: false,
                    message:      text.into(),
                    entities:     None,
                    reply_markup: None,
                }
            ),
        }
    )
}
}

Multiple results for a query

#![allow(unused)]
fn main() {
fn build_results(q: &str) -> Vec<tl::enums::InputBotInlineResult> {
    if q.is_empty() {
        // Default suggestions when query is blank
        return vec![
            article("time", "🕐 Current Time",
                &chrono::Utc::now().format("%H:%M UTC").to_string(),
                &chrono::Utc::now().to_rfc2822()),
            article("help", "📖 Help", "See all commands", "/help"),
        ];
    }

    vec![
        article("u", &format!("UPPER: {}", q.to_uppercase()),
            "Uppercase version", &q.to_uppercase()),
        article("l", &format!("lower: {}", q.to_lowercase()),
            "Lowercase version", &q.to_lowercase()),
        article("r", &format!("Reversed"),
            "Reversed text", &q.chars().rev().collect::<String>()),
        article("c", "📊 Character count",
            &format!("{} chars, {} words", q.len(), q.split_whitespace().count()),
            &format!("{} characters • {} words • {} lines",
                q.chars().count(), q.split_whitespace().count(), q.lines().count())),
    ]
}
}

InlineQuery fields

Field / MethodTypeDescription
iq.query()&strThe text the user typed
iq.query_idi64Unique ID for this query
iq.offset()&strPagination offset
iq.peer_typevariesType of chat where query was issued

InlineSend — when a result is chosen

#![allow(unused)]
fn main() {
Update::InlineSend(is) => {
    // Fired when the user picks one of your results
    println!("Result chosen: {}", is.id());
    // Use this for logging, stats, or post-send actions
}
}

Pagination

For large result sets, implement pagination using next_offset:

#![allow(unused)]
fn main() {
let page: usize = iq.offset().parse().unwrap_or(0);
let items = get_items_page(page, 10);
let next  = if items.len() == 10 { Some(format!("{}", page + 1)) } else { None };

client.answer_inline_query(
    iq.query_id,
    items,
    60,
    false,
    next.as_deref(),
).await?;
}