Skip to main content

Crate ferogram

Crate ferogram 

Source
Expand description

Async Rust client for the Telegram MTProto protocol.

ferogram works with both user accounts and bots. It talks directly to Telegram’s MTProto servers: there is no Bot API HTTP proxy involved.

Built by Ankit Chaubey. Community: t.me/Ferogram (channel) | t.me/FerogramChat (chat)

§Getting started

Add to Cargo.toml:

[dependencies]
ferogram = "0.3"
tokio    = { version = "1", features = ["full"] }

Get api_id and api_hash from my.telegram.org.

§Bot login

use ferogram::{Client, update::Update};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let (client, _shutdown) = Client::builder()
        .api_id(std::env::var("API_ID")?.parse()?)
        .api_hash(std::env::var("API_HASH")?)
        .session("bot.session")
        .connect()
        .await?;

    client.bot_sign_in(&std::env::var("BOT_TOKEN")?).await?;
    client.save_session().await?;

    let mut stream = client.stream_updates();
    while let Some(upd) = stream.next().await {
        if let Update::NewMessage(msg) = upd {
            if !msg.outgoing() {
                if let Some(text) = msg.text() {
                    msg.reply(text).await?;
                }
            }
        }
    }
    Ok(())
}

§User login

use ferogram::{Client, SignInError};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let (client, _shutdown) = Client::builder()
        .api_id(12345)
        .api_hash("your_api_hash")
        .session("my.session")
        .connect()
        .await?;

    if !client.is_authorized().await? {
        let token = client.request_login_code("+1234567890").await?;
        let code  = read_line();
        match client.sign_in(&token, &code).await {
            Ok(name) => println!("Signed in as {name}"),
            Err(SignInError::PasswordRequired(t)) => {
                client.check_password(*t, "2fa_password").await?;
            }
            Err(e) => return Err(e.into()),
        }
        client.save_session().await?;
    }

    client.send_message("me", "Hello from ferogram!").await?;
    Ok(())
}

§What’s covered

Authentication

  • Phone + code + 2FA SRP user login
  • Bot token login
  • Session string export / import

Updates: typed variants from update::Update: NewMessage, MessageEdited, MessageDeleted, CallbackQuery, InlineQuery, InlineSend, UserStatus, UserTyping, ParticipantUpdate, JoinRequest, MessageReaction, PollVote, BotStopped, ShippingQuery, PreCheckoutQuery, ChatBoost, Raw

Messaging

  • Send, edit, delete, forward, pin, unpin
  • Reply-to, schedule, silent flag
  • HTML and Markdown entity formatting (see parsers)
  • Inline keyboards via [keyboard::InlineKeyboardBuilder]

Media

  • Concurrent chunked file upload
  • Media and CDN file download
  • Photo, document, audio, video, sticker

Peers and dialogs

  • Automatic access-hash caching for users, chats, channels
  • Paginated dialog iterator
  • Paginated per-chat message history
  • Global and per-chat message search
  • Mark as read, delete dialogs, clear mentions

Dispatcher and filters (see filters)

  • FLOOD_WAIT auto-retry with configurable policy
  • filters::Dispatcher with composable filter combinators (&, |, !)
  • Middleware chain (pre-handler interception, see middleware)
  • FSM for multi-step conversations (see fsm)

Connection

  • DC migration
  • Transport probing: races Abridged vs Obfuscated connections
  • SOCKS5 proxy (see proxy)
  • DNS-over-HTTPS resolver with TTL cache
  • Reconnect with session persistence

Raw API

  • client.invoke(&req) for any TL function
  • client.invoke_on_dc(dc_id, &req) for specific DCs
  • All of Layer 224 accessible via ferogram::tl

§Dispatcher and filters

use ferogram::filters::{Dispatcher, command, private, text_contains};

let mut dp = Dispatcher::new();

dp.on_message(command("start"), |msg| async move {
    msg.reply("Hello!").await.ok();
});

dp.on_message(private() & text_contains("help"), |msg| async move {
    msg.reply("Type /start to begin.").await.ok();
});

§FSM

use ferogram::{FsmState, fsm::MemoryStorage};
use ferogram::filters::{Dispatcher, command, text};
use std::sync::Arc;

#[derive(FsmState, Clone, Debug, PartialEq)]
enum Form { Name, Age }

let mut dp = Dispatcher::new();
dp.with_state_storage(Arc::new(MemoryStorage::new()));

dp.on_message_fsm(text(), Form::Name, |msg, state| async move {
    state.set_data("name", msg.text().unwrap()).await.ok();
    state.transition(Form::Age).await.ok();
    msg.reply("How old are you?").await.ok();
});

§Session backends

BackendFeature flagNotes
BinaryFileBackenddefaultSingle file on disk
InMemoryBackenddefaultNo persistence, tests
StringSessionBackenddefaultBase64 string, serverless
SqliteBackendsqlite-sessionMulti-session local file
LibSqlBackendlibsql-sessionTurso / distributed libSQL

§Feature flags

FlagWhat it enables
sqlite-sessionSqliteBackend via rusqlite
libsql-sessionLibSqlBackend via libsql-client
htmlparse_html / generate_html (built-in parser)
html5everReplaces parse_html with spec-compliant html5ever
derive#[derive(FsmState)] macro
serdeSerde support for session types
parserRe-exports ferogram-tl-parser for custom tooling
codegenRe-exports ferogram-tl-gen for custom tooling

§Raw API

use ferogram::tl;

let req = tl::functions::messages::GetDialogs {
    offset_date: 0,
    offset_id: 0,
    offset_peer: tl::enums::InputPeer::Empty,
    limit: 20,
    hash: 0,
    exclude_pinned: false,
    folder_id: None,
};
let result = client.invoke(&req).await?;

Re-exports§

pub use fsm::FsmState;
pub use builder::BuilderError;
pub use builder::ClientBuilder;
pub use keyboard::Button;
pub use keyboard::InlineKeyboard;
pub use keyboard::ReplyKeyboard;
pub use media::Document;
pub use media::DownloadIter;
pub use media::Downloadable;
pub use media::Photo;
pub use media::Sticker;
pub use media::UploadedFile;
pub use participants::Participant;
pub use participants::ProfilePhotoIter;
pub use peer_ref::PeerRef;
pub use proxy::MtProxyConfig;
pub use search::GlobalSearchBuilder;
pub use search::SearchBuilder;
pub use socks5::Socks5Config;
pub use types::ChannelKind;
pub use types::Channel;
pub use types::Chat;
pub use types::Group;
pub use types::User;
pub use typing_guard::TypingGuard;
pub use update::BotStoppedUpdate;
pub use update::MessageReactionUpdate;
pub use update::PollVoteUpdate;
pub use update::ButtonFilter;
pub use update::Update;
pub use update::ChatActionUpdate;
pub use update::JoinRequestUpdate;
pub use update::ParticipantUpdate;
pub use update::UserStatusUpdate;
pub use update::ChatBoostUpdate;
pub use update::PreCheckoutQueryUpdate;
pub use update::ShippingQueryUpdate;
pub use ferogram_tl_types as tl;
pub use ferogram_mtproto as mtproto;
pub use ferogram_crypto as crypto;
pub use ferogram_tl_parser as parser;parser
pub use ferogram_tl_gen as codegen;codegen

Modules§

authentication
MTProto authentication key generation (DH handshake steps).
builder
cdn_download
Telegram CDN DC file downloads.
conversation
dc_migration
dc_pool
dns_resolver
DNS-over-HTTPS resolver.
filters
fsm
inline_iter
keyboard
macros
media
message_box
middleware
parsers
participants
peer_ref
persist
proxy
reactions
search
session_backend
socks5
special_config
Firebase / Google special-config fallback.
transport_intermediate
transport_obfuscated
types
typing_guard
update
util

Macros§

dispatch

Structs§

AuthKey
A Telegram authorization key (256 bytes) plus pre-computed identifiers.
AutoSleep
Automatically sleep on FLOOD_WAIT and retry once on transient I/O errors.
BinaryFileBackend
Stores the session in a compact binary file (v2 format).
CircuitBreaker
A RetryPolicy that stops retrying after threshold consecutive failures and stays silent for a cooldown window before resetting.
Client
The main Telegram client. Cheap to clone: internally Arc-wrapped.
Config
Configuration for Client::connect.
DcEntry
One entry in the DC address table.
DcFlags
Per-DC option flags.
Dialog
A Telegram dialog (chat, user, channel).
DialogIter
Cursor-based iterator over dialogs. Created by Client::iter_dialogs.
ExperimentalFeatures
Opt-in experimental behaviours that deviate from strict Telegram spec.
ExponentialBackoff
Exponential backoff with jitter.
Finished
The final output of a successful auth key handshake.
FixedInterval
ForwardOptions
Options for forwarding messages.
InMemoryBackend
Ephemeral in-process session: nothing persisted to disk.
InputMessage
Builder for composing outgoing messages.
LoginToken
Opaque token returned by crate::Client::request_login_code.
MessageIter
Cursor-based iterator over message history. Created by Client::iter_messages.
MiniAppSession
An active mini-app session returned by Client::open_mini_app.
NeverRestart
NoRetries
Never retry: propagate every error immediately.
PasswordToken
Opaque 2FA challenge token returned in SignInError::PasswordRequired.
PeerCache
Caches access hashes for users and channels so every API call carries the correct hash without re-resolving peers.
RetryContext
Context passed to RetryPolicy::should_retry on each failure.
RpcError
An error returned by Telegram’s servers in response to an RPC call.
SqliteBackendsqlite-session
SQLite-backed session (via rusqlite).
StringSessionBackend
Portable base64 string session backend.
UpdateStream
Asynchronous stream of Updates.

Enums§

InvocationError
The error type returned from any Client method that talks to Telegram.
LinkKind
Selects which flavour of message link Client::export_message_link should produce.
MiniApp
Which kind of mini-app to open.
SignInError
Errors returned by crate::Client::sign_in.
TransportKind
UpdateStateChange
A single update-sequence change, applied via SessionBackend::apply_update_state.

Constants§

LAYER
The API layer this code was generated from.

Traits§

ConnectionRestartPolicy
Identifiable
Every generated type has a unique 32-bit constructor ID.
RetryPolicy
Controls how the client reacts when an RPC call fails.
Serializable
SessionBackend
Synchronous snapshot backend: saves and loads the full session at once.

Functions§

finish
Finalise the handshake.
step1
Generate a req_pq_multi request. Returns the request + opaque state.
step2
Process ResPQ and generate req_DH_params.
step3
Process ServerDhParams into a reusable DhParamsForRetry + send the first set_client_DH_params request.

Type Aliases§

ShutdownToken
A token that can be used to gracefully shut down a Client.