td_client/lib.rs
1//! Typed asynchronous access to [`TDLib`](https://core.telegram.org/tdlib).
2//!
3//! This crate connects generated `td-types` requests to `TDLib`, receives ordered
4//! updates, and tracks message sends and downloads. It is a native Telegram client
5//! integration for bots and user accounts, not an HTTP Bot API wrapper.
6//!
7//! # Getting started
8//!
9//! The workspace crates are not published. Use local path dependencies on
10//! `td-client` and `td-types`, plus Tokio with the features your application
11//! needs. For example, from another directory beside this checkout:
12//!
13//! ```toml
14//! [dependencies]
15//! td-client = { path = "../td/td-client" }
16//! td-types = { path = "../td/td-types" }
17//! tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
18//! ```
19//!
20//! The Rust API is generated from `td/td_api.tl` at build time. Fetch a matching
21//! native library and schema with `./td/fetch` from the repository root before
22//! building. The supplied fetch script uses Bash 4+, curl, jq, and tar; on Linux
23//! it also uses readelf. It selects Linux glibc or macOS packages for the host
24//! architecture. The workspace requires Rust 1.98 or newer. Keep the native
25//! library and generated schema in sync; updating only one can cause decoding
26//! failures or unsupported requests.
27//!
28//! ## Native linking and deployment
29//!
30//! The build helper searches the checkout's `td/` directory and dynamically
31//! links `tdjson`. An external application must also make that shared library
32//! discoverable at runtime. Cargo does not propagate a dependency's executable
33//! runtime-path flags into every downstream binary.
34//!
35//! For local applications, add `td-sys` as a path build-dependency and call its
36//! helper from `main` in your application's `build.rs`:
37//!
38//! ```no_run
39//! td_sys::build::link();
40//! ```
41//!
42//! On Linux/macOS the helper adds runtime search paths for the executable's
43//! directory and the local native-library directory. Deployment still requires
44//! shipping/installing the matching shared library (including the name expected
45//! by the platform loader) and its native dependencies. A loader error is not an
46//! authentication error; check library placement before debugging credentials.
47//! The fetch script is host-oriented, not a cross-compilation setup. For other
48//! targets, supply the appropriate native artifacts and platform linker/loader
49//! configuration yourself.
50//!
51//! Obtain an API ID and hash from [Telegram](https://my.telegram.org/apps).
52//! Bots additionally need a token from [BotFather](https://t.me/BotFather).
53//! Keep credentials and session directories out of version control.
54//!
55//! # A request and a clean closure
56//!
57//! A [`Session`] owns one `TDLib` instance. Obtain a
58//! [`Client`] for requests; keep the owner until closure.
59//! A request's generated type determines its response type:
60//!
61//! ```no_run
62//! use td_client::types::{enums::User, fns};
63//! use td_client::{Session, parameters};
64//! use td_client::Result;
65//!
66//! # async fn example(api_id: i32, api_hash: &str, token: &str) -> Result {
67//! let mut session = Session::bot(parameters(api_id, api_hash, "session"), token).await?;
68//! let result = session.client().send(&fns::getMe {}).await;
69//! let close = session.close().await;
70//!
71//! // Attempt cleanup even when the application request fails.
72//! let User::user(user) = result?;
73//! close?;
74//! println!("Signed in as {}", user.first_name);
75//! # Ok(())
76//! # }
77//! ```
78//!
79//! Do not put a fallible application's entire body before `close().await?`
80//! using unchecked early `?` returns: they can drop the owner without closing
81//! `TDLib`. Save the application result, attempt close, then choose how to
82//! report either or both errors. Dropping an unfinished constructor or close
83//! future also abandons graceful cleanup.
84//!
85//! # Choosing an operation
86//!
87//! | Method | What its result means |
88//! | --- | --- |
89//! | [`Client::send`](client::Client::send) | The function's direct `TDLib` response |
90//! | [`Client::track`](client::Client::track) | One normal send reached its terminal outcome |
91//! | [`Client::track_all`](client::Client::track_all) | Ordered individual outcomes for a normal-send batch |
92//! | [`Client::download`](client::Client::download) | `TDLib` finished the synchronous download request |
93//! | [`execute`] | A synchronously executable function returned |
94//!
95//! Use direct requests for getters, edits, previews, and other API functions.
96//! Only normal sends belong on tracked message methods; the [message] module
97//! explains the distinction and cancellation races. The [transfer] module
98//! describes measurements, download ranges, and callback requirements.
99//!
100//! # Requests, updates, and ownership
101//!
102//! Clients are cloneable and can be moved into independent tasks. They cannot
103//! receive updates, close the session, or keep it operational after its owner
104//! drops. Requests may run concurrently; response arrival is not submission
105//! order. The owner alone consumes updates through
106//! [`recv`](session::Session::recv) and authorization through
107//! [`recv_auth`](session::Session::recv_auth).
108//!
109//! One process-wide native receiver routes all clients. It resolves requests and
110//! tracked sends independently of application polling. Original application
111//! updates remain ordered and unchanged; authorization updates use the separate
112//! auth API. The queue is unbounded, so applications must drain it to avoid
113//! accumulating memory. Dispatch slow work separately from the receive loop.
114//!
115//! Do not run this crate alongside another `TDLib` receiver implementation in the
116//! same process. Do not call raw receive functions behind its back: the
117//! native receive stream has one coordinated owner.
118//!
119//! # Generated API vocabulary
120//!
121//! `td-types::fns` contains requests, `td-types::types` concrete payloads,
122//! and `td-types::enums` tagged unions. Names preserve `TDLib` spelling.
123//! `td-types::traits::Function` associates each request with its return type.
124//! Defaults make wide request construction convenient, but do not guarantee that
125//! the resulting arguments are valid for `TDLib`.
126//!
127//! These crates are built locally; references to their items are written as code
128//! rather than links to an assumed hosted documentation tree.
129//!
130//! # Errors and application policy
131//!
132//! [`error::Error`] distinguishes native errors, JSON failures, terminal message
133//! failures, cancellation, and disconnection. Unsolicited diagnostics without a
134//! request recipient go only to the optional [`on_error`] callback.
135//! A malformed terminal update may leave a tracked send waiting indefinitely.
136//!
137//! The crate supplies no request deadlines, retries, scheduling, or rate-limit
138//! policy. A timeout that drops a request future does not undo its native work;
139//! see [`Client::send`](client::Client::send) and the tracked methods before
140//! retrying an operation that might already have taken effect.
141//!
142//! `TDLib` handles its own network/protocol behavior. The wrapper does not promise
143//! that every failure is retryable, that cancelling is server-atomic, or that a
144//! successful progress callback means an operation is complete.
145
146pub mod client;
147pub mod error;
148pub mod message;
149pub mod runtime;
150pub mod session;
151pub mod transfer;
152
153mod connection;
154
155pub use td_types as types;
156
157pub use crate::client::*;
158pub use crate::error::*;
159pub use crate::message::*;
160pub use crate::runtime::*;
161pub use crate::session::*;
162pub use crate::transfer::*;