ferogram
Async Rust client for the Telegram MTProto API.
Built by Ankit Chaubey
Pre-production. APIs may change between minor versions. Check CHANGELOG before upgrading.
What it is
ferogram is the high-level client crate in the ferogram workspace. It talks to Telegram directly over MTProto, no Bot API HTTP proxy. Works for both user accounts and bots.
For the full workspace (crypto, session, TL types, etc.) see the repository root.
Installation
[]
= "0.3"
= { = "1", = ["full"] }
Get api_id and api_hash from my.telegram.org.
Optional feature flags:
= { = "0.3", = [
"sqlite-session", # SqliteBackend via rusqlite
"libsql-session", # LibSqlBackend via libsql-client (Turso)
"html", # parse_html / generate_html (built-in parser)
"html5ever", # parse_html via spec-compliant html5ever
"derive", # #[derive(FsmState)]
"serde", # serde support for session types
] }
Connecting
use Client;
let = builder
.api_id
.api_hash
.session
.catch_up
.connect
.await?;
ClientBuilder methods
| Method | Description |
|---|---|
.api_id(i32) |
Telegram API ID (required) |
.api_hash(str) |
Telegram API hash (required) |
.session(path) |
Binary file session at path |
.session_string(s) |
Portable base64 string session |
.in_memory() |
Non-persistent in-memory session |
.session_backend(Arc<dyn SessionBackend>) |
Custom backend |
.catch_up(bool) |
Replay missed updates on reconnect (default: false) |
.dc_addr(str) |
Override first DC address |
.socks5(Socks5Config) |
Route through SOCKS5 proxy |
.proxy_link(str) |
MTProxy t.me/proxy?... link |
.allow_ipv6(bool) |
Allow IPv6 DC addresses (default: false) |
.transport(TransportKind) |
MTProto transport (Abridged, Obfuscated, FakeTls) |
.probe_transport(bool) |
Race transports, use the first to connect (default: false) |
.resilient_connect(bool) |
Fall back through DoH + Telegram special-config on TCP failure |
.retry_policy(Arc<dyn RetryPolicy>) |
Override flood-wait retry policy |
.restart_policy(Arc<dyn ConnectionRestartPolicy>) |
Override reconnect policy |
.device_model(str) |
Device model string sent in InitConnection |
.system_version(str) |
System version string |
.app_version(str) |
App version string |
.experimental_features(ExperimentalFeatures) |
Opt-in to non-default behaviors |
.connect() |
Build and connect, returns (Client, ShutdownToken) |
Authentication
// Bot login
if !client.is_authorized.await?
// User login
use SignInError;
if !client.is_authorized.await?
// QR code login (for clients where keyboard input is not available)
let = client.export_login_token.await?;
// Display as QR code, then poll:
if let Some = client.check_qr_login.await?
// Sign out
client.sign_out.await?;
Session export / restore
let s = client.export_session_string.await?;
let = builder
.api_id
.api_hash
.session_string
.connect
.await?;
Update stream
use Update;
let mut stream = client.stream_updates;
while let Some = stream.next.await
IncomingMessage accessors: id(), text(), text_html(), text_markdown(), peer_id(), sender_id(), sender(), outgoing(), date(), edit_date(), mentioned(), silent(), pinned(), post(), has_media(), is_photo(), is_document(), download_media_with(), command(), reply(), raw.
Dispatcher and filters
use ;
let mut dp = new;
dp.on_message;
dp.on_message;
dp.on_message;
while let Some = stream.next.await
Built-in filter functions: all, none, private, group, channel, text, text_contains, command, media, photo, document, audio, video, sticker, regex, custom, from_user, outgoing, incoming.
Filters compose with & (both), | (either), ! (not).
Middleware
use Dispatcher;
let mut dp = new;
dp.middleware;
Middleware runs in registration order before any handler. Calling next.run(upd) passes control down the chain. Returning early skips all remaining middleware and the handler.
FSM
use ;
use ;
use Arc;
let mut dp = new;
dp.with_state_storage;
dp.on_message;
dp.on_message_fsm;
dp.on_message_fsm;
State storage: MemoryStorage is built in. Implement StateStorage for Redis, SQL, or any other backend. State keys can be scoped per-user, per-chat, or per-user-in-chat via StateKeyStrategy.
Messaging
client.send_message.await?;
client.send_message.await?;
client.send_to_self.await?;
client.send_message_to_peer.await?;
client.edit_message.await?;
client.forward_messages.await?;
client.delete_messages.await?;
client.pin_message.await?;
client.unpin_message.await?;
client.unpin_all_messages.await?;
// Get reply-to message
let replied = client.get_reply_to_message.await?;
InputMessage builder
use InputMessage;
use ;
let kb = new
.row
.row;
client.send_message_to_peer_ex.await?;
| Method | Description |
|---|---|
InputMessage::text(str) |
Plain text |
InputMessage::markdown(str) |
Parse Telegram Markdown |
InputMessage::html(str) |
Parse HTML |
.reply_to(Option<i32>) |
Reply to message ID |
.silent(bool) |
No notification sound |
.background(bool) |
Background message |
.no_webpage(bool) |
Suppress link preview |
.invert_media(bool) |
Show media above caption |
.schedule_date(Option<i32>) |
Schedule for Unix timestamp |
.schedule_once_online() |
Send when peer comes online |
.entities(Vec<MessageEntity>) |
Pre-computed entities |
.keyboard(impl Into<ReplyMarkup>) |
Inline or reply keyboard |
.copy_media(InputMedia) |
Attach media |
.clear_media() |
Remove attached media |
Scheduled messages
let scheduled = client.get_scheduled_messages.await?;
client.delete_scheduled_messages.await?;
client.send_scheduled_now.await?;
Keyboards
use ;
// Inline keyboard
let kb = new
.row;
// Reply keyboard
let kb = new
.row
.resize
.single_use
.placeholder;
// Answer callback query
CallbackQuery =>
// Answer inline query
InlineQuery =>
Full button types: callback, url, url_auth, switch_inline, switch_inline_chosen_peer, switch_inline_current_chat, webview, simple_webview, request_phone, request_geo, request_poll, request_quiz, game, buy, copy_text, text.
Media
use Arc;
// Upload from bytes
let file = client.upload_file.await?;
let file = client.upload_file_concurrent.await?;
// Upload from AsyncRead stream
let file = client.upload_stream.await?;
// Upload arbitrary InputMedia (stickers, thumbnails, etc.)
let media = client.upload_media.await?;
// Send
client.send_file.await?; // false = as document
client.send_file.await?; // true = as photo
client.send_album.await?; // grouped
// Download to memory
let bytes = client.download_media.await?;
let bytes = client.download_media_concurrent.await?;
// Download to file
client.download_media_to_file.await?;
client.download_media_to_file_on_dc.await?;
// Implement Downloadable on your own types for download()
let bytes = client.download.await?;
// CDN downloads (large media)
let iter = client.iter_download;
Text formatting
// Telegram-flavoured Markdown
use ;
let = parse_markdown;
// HTML (requires "html" feature)
use ;
let = parse_html;
// InputMessage has shorthand for both:
markdown
html
Reactions
use InputReactions;
client.send_reaction.await?;
client.send_reaction.await?;
client.send_reaction.await?;
client.send_paid_reaction.await?;
client.read_reactions.await?;
client.clear_recent_reactions.await?;
let reactions = client.get_message_reactions.await?;
let list = client.get_reaction_list.await?;
Typing indicators
TypingGuard sends the action on construction and cancels it on drop:
let _typing = client.typing.await?;
let _uploading = client.uploading_document.await?;
let _recording = client.recording_video.await?;
use TypingGuard;
let _guard = start.await?;
Dialogs
let dialogs = client.get_dialogs.await?;
// Lazy paginated iterator
let mut iter = client.iter_dialogs;
while let Some = iter.next.await?
// Pinned, archive
let pinned = client.get_pinned_dialogs.await?;
client.pin_dialog.await?;
client.unpin_dialog.await?;
client.archive_chat.await?;
client.unarchive_chat.await?;
client.mark_dialog_unread.await?;
// Drafts
client.save_draft.await?;
client.get_all_drafts.await?;
client.clear_all_drafts.await?;
Message history
let msgs = client.get_messages.await?;
let msgs = client.get_messages_by_id.await?;
let pinned = client.get_pinned_message.await?;
// Lazy paginated iterator (reverse chronological)
let mut iter = client.iter_messages;
while let Some = iter.next.await?
client.mark_as_read.await?;
client.clear_mentions.await?;
client.delete_dialog.await?;
// Get media group (album)
let group = client.get_media_group.await?;
// Message read participants (premium feature)
let readers = client.get_message_read_participants.await?;
// Export message link
let link = client.export_message_link.await?;
Search
use MessagesFilter;
// In-chat search with builder
let results = client
.search
.filter
.from_user
.limit
.fetch
.await?;
// Global search with builder
let results = client
.search_global_builder
.broadcasts_only
.limit
.fetch
.await?;
// Quick helpers
let results = client.search_messages.await?;
let results = client.search_global.await?;
Participants
use ;
let members = client.get_participants.await?;
client.kick_participant.await?;
client.ban_participant.await?;
client.ban_participant.await?;
client.promote_participant.await?;
let photos = client.get_profile_photos.await?;
Chat management
// Create
let chat = client.create_group.await?;
let channel = client.create_channel.await?;
// Edit
client.edit_chat_title.await?;
client.edit_chat_about.await?;
client.edit_chat_photo.await?;
client.edit_chat_default_banned_rights.await?;
// Membership
client.invite_users.await?;
client.leave_chat.await?;
client.delete_channel.await?;
client.delete_chat.await?;
client.migrate_chat.await?; // basic group -> supergroup
// Info
let full = client.get_chat_full.await?;
let admins = client.get_chat_administrators.await?;
let online = client.get_online_count.await?;
let common = client.get_common_chats.await?;
let count = client.count_channels.await?;
// Invite links
let link = client.export_invite_link.await?;
let links = client.get_invite_links.await?;
client.revoke_invite_link.await?;
client.edit_invite_link.await?;
client.delete_invite_link.await?;
client.delete_revoked_invite_links.await?;
let members = client.get_invite_link_members.await?;
let admins_invites = client.get_admins_with_invites.await?;
// Misc
client.toggle_no_forwards.await?;
client.set_chat_theme.await?;
client.set_chat_reactions.await?;
let send_as = client.get_send_as_peers.await?;
client.set_default_send_as.await?;
client.transfer_chat_ownership.await?;
let linked = client.get_linked_channel.await?;
// Forum topics (supergroups with topics enabled)
let topics = client.get_forum_topics.await?;
client.create_forum_topic.await?;
client.edit_forum_topic.await?;
client.delete_forum_topic_history.await?;
client.toggle_forum.await?;
Contacts
let contacts = client.get_contacts.await?;
client.add_contact.await?;
client.delete_contacts.await?;
client.import_contacts.await?;
let results = client.search_contacts.await?;
client.block_user.await?;
client.unblock_user.await?;
Profile
client.update_profile.await?;
client.update_username.await?;
client.update_status.await?; // false = online, true = offline
client.set_profile_photo.await?;
client.delete_profile_photos.await?;
client.set_emoji_status.await?;
let full = client.get_user_full.await?;
// Active sessions
let sessions = client.get_authorizations.await?;
client.terminate_session.await?;
Polls
client.send_poll.await?;
let results = client.get_poll_results.await?;
let votes = client.get_poll_votes.await?;
client.send_vote.await?;
Bot-specific
// Set commands
client.set_bot_commands.await?;
client.delete_bot_commands.await?;
// Bot info
client.set_bot_info.await?;
let info = client.get_bot_info.await?;
// Inline message editing (from inline send)
client.edit_inline_message.await?;
// Games
client.start_bot.await?;
client.set_game_score.await?;
let scores = client.get_game_high_scores.await?;
// Payments
client.send_invoice.await?;
client.answer_shipping_query.await?;
client.answer_precheckout_query.await?;
// Reply to join request
// Update::JoinRequest(j) => approve or decline via j.approve(&client)
Discussions and replies
let thread = client.get_replies.await?;
let discussion = client.get_discussion_message.await?;
client.read_discussion.await?;
Translation and transcription
let translated = client.translate_messages.await?;
let transcript = client.transcribe_audio.await?;
client.toggle_peer_translations.await?;
Stickers
let set = client.get_sticker_set.await?;
client.install_sticker_set.await?;
client.uninstall_sticker_set.await?;
let all = client.get_all_stickers.await?;
let docs = client.get_custom_emoji_documents.await?;
Privacy and notifications
use InputPrivacyKey;
let rules = client.get_privacy.await?;
client.set_privacy.await?;
let settings = client.get_notify_settings.await?;
client.update_notify_settings.await?;
Admin log
let events = client.get_admin_log.await?;
Channel and megagroup stats
let broadcast_stats = client.get_broadcast_stats.await?;
let megagroup_stats = client.get_megagroup_stats.await?;
Peer resolution
// From username, phone, or t.me link
let peer = client.resolve_peer.await?;
let peer = client.resolve_peer.await?;
let peer = client.resolve_username.await?;
let input_peer = client.resolve_to_input_peer.await?;
let hash = parse_invite_hash?;
Transport and proxy
use ;
// Choose transport
builder.transport // default
builder.transport // DPI bypass
builder.transport // TLS camouflage
// MTProxy (parses t.me/proxy or t.me/+proxy links)
builder.proxy_link
// SOCKS5
builder.socks5
builder.socks5
// Race transports, use first to connect
builder.probe_transport
// Fall back through DNS-over-HTTPS and Telegram special-config if TCP fails
builder.resilient_connect
Session backends
use ;
use Arc;
builder.session // binary file
builder.in_memory // no persistence
builder.session_string // base64 string
builder.session_backend // sqlite
builder.session_backend // turso
Custom: implement SessionBackend from ferogram_session.
Error handling
use ;
match client.send_message.await
FLOOD_WAIT is handled automatically. To disable:
use NoRetries;
builder.retry_policy
Raw API
Every Layer 224 TL method is accessible directly:
use tl;
let req = SetBotCommands ;
client.invoke.await?;
client.invoke_on_dc.await?;
Shutdown
let = builder...connect.await?;
shutdown.cancel; // graceful shutdown
client.disconnect; // immediate disconnect
Full Feature List
For everything ferogram supports (auth, media, FSM, polls, admin rights, privacy, games, raw API, and more) see FEATURES.md.
Community
- Channel (announcements, releases): t.me/Ferogram
- Chat (questions, support): t.me/FerogramChat
- API docs: docs.rs/ferogram
- Guide: ferogram.ankitchaubey.in
- GitHub: github.com/ankit-chaubey/ferogram
Author
Developed by Ankit Chaubey.
License
MIT OR Apache-2.0. See LICENSE-MIT and LICENSE-APACHE.
Usage must comply with Telegram's API Terms of Service.