SkillAgentSearch skills...

Tgbotrs

A strongly-typed, async Rust client for the Telegram Bot API, generated from the official spec.

Install / Use

/learn @ankit-chaubey/Tgbotrs
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<div align="center"> <img src="https://rustacean.net/assets/rustacean-orig-noshadow.svg" width="110" alt="Ferris the Crab"/> <h1>tgbotrs</h1> <p><strong>A fully-featured, auto-generated Telegram Bot API library for Rust 🦀</strong></p>

Crates.io docs.rs CI API Sync

Bot API Rust Types Methods Coverage Downloads License

<br/>

All 285 types and 165 methods of the Telegram Bot API —
strongly typed, fully async, automatically kept in sync with every official release.

<br/>

📦 Install · 🚀 Quick Start · 📖 Examples · 🔧 API Reference · 🔄 Auto-Codegen · 📚 docs.rs

</div>

✨ Features

<table> <tr> <td width="50%">

🤖 Complete API Coverage

  • All 285 types — structs, enums, markers
  • All 165 methods — fully async
  • All 21 union types as Rust enums
  • 100 optional params structs with builder pattern
</td> <td width="50%">

🔄 Auto-Generated & Always Fresh

  • Spec sourced from tgapis/x — auto-updated every 6 hours
  • Pipeline dispatches regeneration on every new API version
  • PR auto-opened with full semantic diff on every change
  • Zero manual work to stay up-to-date
</td> </tr> <tr> <td>

🦀 Idiomatic Rust

  • Fully async/await with Tokio
  • Into<ChatId> — accepts i64 or "@username"
  • Into<String> on all text params
  • Option<T> for all optional fields
  • Box<T> to break recursive type cycles
</td> <td>

🛡️ Fully Type-Safe

  • ChatId — integer or username, no stringly typing
  • InputFile — file_id / URL / raw bytes
  • ReplyMarkup — unified enum for all 4 keyboard types
  • InputMedia — typed enum for media groups
  • Compile-time guarantees on every API call
</td> </tr> <tr> <td>

📡 Flexible HTTP Layer

  • Custom API server support (local Bot API)
  • Multipart file uploads built-in
  • Configurable timeout
  • Flood-wait aware error handling
  • reqwest backend
</td> <td>

📬 Built-in Polling

  • Long-polling dispatcher included
  • Spawns a Tokio task per update
  • Configurable timeout, limit, allowed_updates
  • Clean concurrent update processing
</td> </tr> </table>

📦 Installation

Add to your Cargo.toml:

[package]
name = "mybot"
version = "0.1.0"
edition = "2021"

[dependencies]
tgbotrs = ">=0.1.5"
tokio   = { version = "1", features = ["full"] }

Requirements: Rust 1.75+ · Tokio async runtime


🚀 Quick Start

use tgbotrs::Bot;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let bot = Bot::new("YOUR_BOT_TOKEN").await?;

    println!("✅ Running as @{}", bot.me.username.as_deref().unwrap_or("unknown"));
    println!("   ID: {}", bot.me.id);

    // chat_id accepts i64, negative group IDs, or "@username"
    let msg = bot.send_message(123456789i64, "Hello from tgbotrs! 🦀", None).await?;
    println!("📨 Sent message #{}", msg.message_id);

    Ok(())
}

📖 Examples

🔁 Echo Bot — Long Polling

The simplest possible bot. Receives every message and echoes it back.

use tgbotrs::{Bot, Poller, UpdateHandler};

#[tokio::main]
async fn main() {
    let bot = Bot::new(std::env::var("BOT_TOKEN").unwrap())
        .await
        .expect("Invalid token");

    println!("🤖 @{} is running...", bot.me.username.as_deref().unwrap_or(""));

    let handler: UpdateHandler = Box::new(|bot, update| {
        Box::pin(async move {
            let Some(msg) = update.message else { return };
            let Some(text) = msg.text else { return };
            let _ = bot.send_message(msg.chat.id, text, None).await;
        })
    });

    Poller::new(bot, handler)
        .timeout(30)
        .limit(100)
        .start()
        .await
        .unwrap();
}

💬 Formatted Messages

Send HTML or MarkdownV2 formatted messages with optional settings.

use tgbotrs::gen_methods::SendMessageParams;

let params = SendMessageParams::new()
    .parse_mode("HTML".to_string())
    .disable_notification(true);

bot.send_message(
    "@mychannel",
    "<b>Bold</b> · <i>Italic</i> · <code>code</code> · <a href='https://example.com'>Link</a>",
    Some(params),
).await?;

🎹 Inline Keyboards

Buttons embedded inside messages. Perfect for interactive menus.

use tgbotrs::{ReplyMarkup, gen_methods::SendMessageParams};
use tgbotrs::types::{InlineKeyboardButton, InlineKeyboardMarkup};

let keyboard = InlineKeyboardMarkup {
    inline_keyboard: vec![
        vec![
            InlineKeyboardButton {
                text: "✅ Accept".into(),
                callback_data: Some("accept".into()),
                ..Default::default()
            },
            InlineKeyboardButton {
                text: "❌ Decline".into(),
                callback_data: Some("decline".into()),
                ..Default::default()
            },
        ],
        vec![
            InlineKeyboardButton {
                text: "🌐 Visit Website".into(),
                url: Some("https://ankitchaubey.in".into()),
                ..Default::default()
            },
        ],
    ],
};

let params = SendMessageParams::new()
    .parse_mode("HTML".to_string())
    .reply_markup(ReplyMarkup::InlineKeyboard(keyboard));

bot.send_message(chat_id, "<b>Make a choice:</b>", Some(params)).await?;

⚡ Callback Queries

Handle button taps from inline keyboards. Always acknowledge with answer_callback_query.

use tgbotrs::gen_methods::{AnswerCallbackQueryParams, EditMessageTextParams};
use tgbotrs::types::MaybeInaccessibleMessage;

let handler: UpdateHandler = Box::new(|bot, update| {
    Box::pin(async move {
        let Some(cq) = update.callback_query else { return };
        let data = cq.data.as_deref().unwrap_or("");

        // Always acknowledge — dismisses the loading spinner
        let _ = bot
            .answer_callback_query(
                cq.id.clone(),
                Some(
                    AnswerCallbackQueryParams::new()
                        .text(format!("You chose: {}", data))
                        .show_alert(false),
                ),
            )
            .await;

        // Edit the original message in-place
        if let Some(msg) = &cq.message {
            if let MaybeInaccessibleMessage::Message(m) = msg.as_ref() {
                let edit_params = EditMessageTextParams::new()
                    .chat_id(m.chat.id)
                    .message_id(m.message_id)
                    .parse_mode("HTML".to_string());

                let _ = bot
                    .edit_message_text(
                        format!("✅ You selected: <b>{}</b>", data),
                        Some(edit_params),
                    )
                    .await;
            }
        }
    })
});

⌨️ Reply Keyboards

Custom keyboard shown at the bottom of the screen. Great for persistent menu buttons.

use tgbotrs::{ReplyMarkup, gen_methods::SendMessageParams};
use tgbotrs::types::{KeyboardButton, ReplyKeyboardMarkup};

let keyboard = ReplyKeyboardMarkup {
    keyboard: vec![
        vec![
            KeyboardButton {
                text: "📍 Share Location".into(),
                request_location: Some(true),
                ..Default::default()
            },
            KeyboardButton {
                text: "📱 Share Contact".into(),
                request_contact: Some(true),
                ..Default::default()
            },
        ],
        vec![
            KeyboardButton { text: "🏠 Home".into(), ..Default::default() },
            KeyboardButton { text: "⚙️ Settings".into(), ..Default::default() },
        ],
    ],
    resize_keyboard: Some(true),
    one_time_keyboard: Some(true),
    ..Default::default()
};

let params = SendMessageParams::new()
    .reply_markup(ReplyMarkup::ReplyKeyboard(keyboard));

bot.send_message(chat_id, "Use the keyboard below 👇", Some(params)).await?;

📸 Send Photos & Files

Send files by file_id, URL, or raw bytes from disk.

use tgbotrs::{InputFile, gen_methods::SendPhotoParams};

let params = SendPhotoParams::new()
    .caption("Look at this! 📷".to_string())
    .parse_mode("HTML".to_string());

// Fastest — already on Telegram's servers
bot.send_photo(chat_id, "AgACAgIAAxkBAAI...", Some(params.clone())).await?;

// Let Telegram download from a U

Related Skills

View on GitHub
GitHub Stars13
CategoryProduct
Updated1mo ago
Forks15

Languages

Rust

Security Score

95/100

Audited on Mar 1, 2026

No findings