### Full Authorization and get_me Example with Tokio Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Demonstrates the complete authorization flow using Tokio, mpsc channels, and atomic flags. Requires setting up dependencies in Cargo.toml and a build.rs file. ```rust // Cargo.toml: // [dependencies] // tdlib-rs = { version = "1.4.0", features = ["download-tdlib"] } // tokio = { version = "1", features = ["macros", "rt-multi-thread", "sync", "time"] } // // [build-dependencies] // tdlib-rs = { version = "1.4.0", features = ["download-tdlib"] } // // build.rs: // fn main() { tdlib_rs::build::build(None); } use std::sync::{Arc, atomic::{AtomicBool, Ordering}}; use tdlib_rs::{ enums::{self, AuthorizationState, Update, User}, functions, }; use tokio::sync::mpsc::{self, Receiver, Sender}; fn ask_user(prompt: &str) -> String { println!("{prompt}"); let mut buf = String::new(); std::io::stdin().read_line(&mut buf).unwrap(); buf.trim().to_string() } async fn handle_update(update: Update, tx: &Sender) { if let Update::AuthorizationState(u) = update { tx.send(u.authorization_state).await.unwrap(); } } async fn auth_loop( client_id: i32, mut rx: Receiver, run_flag: Arc, ) -> Receiver { while let Some(state) = rx.recv().await { match state { AuthorizationState::WaitTdlibParameters => { functions::set_tdlib_parameters( false, "myapp_db".into(), String::new(), String::new(), false, false, false, false, /* api_id: */ 12345, /* api_hash: */ "your_api_hash_here".into(), "en".into(), "Desktop".into(), String::new(), "1.0.0".into(), client_id, ).await.unwrap(); } AuthorizationState::WaitPhoneNumber => loop { let phone = ask_user("Enter phone number (+country code):"); if functions::set_authentication_phone_number(phone, None, client_id) .await.is_ok() { break; } }, AuthorizationState::WaitCode(_) => loop { let code = ask_user("Enter verification code:"); if functions::check_authentication_code(code, client_id) .await.is_ok() { break; } }, AuthorizationState::WaitPassword(_) => { let pw = ask_user("Enter 2FA password:"); functions::check_authentication_password(pw, client_id).await.unwrap(); } AuthorizationState::WaitRegistration(_) => { let first = ask_user("First name:"); let last = ask_user("Last name:"); functions::register_user(first, last, false, client_id).await.unwrap(); } AuthorizationState::Ready => break, AuthorizationState::Closed => { run_flag.store(false, Ordering::Release); break; } _ => {} } } rx } #[tokio::main] async fn main() { let client_id = tdlib_rs::create_client(); let (tx, rx) = mpsc::channel::(5); let run_flag = Arc::new(AtomicBool::new(true)); let run_flag2 = run_flag.clone(); // Spawn background task to receive TDLib updates let handle = tokio::spawn(async move { while run_flag2.load(Ordering::Acquire) { let result = tokio::task::spawn_blocking(tdlib_rs::receive).await.unwrap(); if let Some((update, _cid)) = result { handle_update(update, &tx).await; } else { tokio::time::sleep(std::time::Duration::from_millis(10)).await; } } }); // Bootstrap the event loop with a first request functions::set_log_verbosity_level(2, client_id).await.unwrap(); // Drive the authorization state machine to Ready let rx = auth_loop(client_id, rx, run_flag.clone()).await; // Fetch own profile let User::User(me) = functions::get_me(client_id).await.unwrap(); println!("Authenticated as: {} {}", me.first_name, me.last_name); // Shut down functions::close(client_id).await.unwrap(); auth_loop(client_id, rx, run_flag.clone()).await; handle.await.unwrap(); } ``` -------------------------------- ### Link Locally Installed TDLib with tdlib-rs Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Configure tdlib-rs to link against a locally compiled or downloaded TDLib installation. Set the `LOCAL_TDLIB_PATH` environment variable to the root of your TDLib installation, which must contain `lib/` and `include/` subdirectories. Enable the `local-tdlib` feature. ```bash # Shell / .bashrc export LOCAL_TDLIB_PATH=$HOME/lib/tdlib ``` ```toml # Cargo.toml [dependencies] tdlib-rs = { version = "1.4.0", features = ["local-tdlib"] } [build-dependencies] tdlib-rs = { version = "1.4.0", features = ["local-tdlib"] } ``` ```rust // build.rs fn main() { tdlib_rs::build::check_features(); tdlib_rs::build::set_rerun_if(); tdlib_rs::build::build_local_tdlib(); } ``` -------------------------------- ### Enable pkg-config Feature in Cargo.toml Source: https://github.com/federicobruzzone/tdlib-rs/blob/main/README.md To use 'pkg-config' for building, enable the 'pkg-config' feature in Cargo.toml. This requires TDLib to be compiled and installed, with PKG_CONFIG_PATH and LD_LIBRARY_PATH environment variables set. ```toml [dependencies] tdlib = { version = "...", features = [ "pkg-config" ] } [build-dependencies] tdlib = { version = "...", features = [ "pkg-config" ] } ``` -------------------------------- ### `tdlib_rs::build::build_local_tdlib` Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Links a locally installed TDLib by reading the `LOCAL_TDLIB_PATH` environment variable. The specified directory must contain `lib/` and `include/` subdirectories. ```APIDOC ## `tdlib_rs::build::build_local_tdlib` — Link a locally installed TDLib Reads the `LOCAL_TDLIB_PATH` environment variable and configures Cargo linker flags to point at a locally compiled or manually downloaded TDLib installation. The folder at `LOCAL_TDLIB_PATH` must contain `lib/` and `include/` subdirectories. ### Usage Set the environment variable: ```bash # Shell / .bashrc export LOCAL_TDLIB_PATH=$HOME/lib/tdlib ``` Add the following to your `Cargo.toml`: ```toml [dependencies] tdlib-rs = { version = "1.4.0", features = ["local-tdlib"] } [build-dependencies] tdlib-rs = { version = "1.4.0", features = ["local-tdlib"] } ``` In your `build.rs`: ```rust // build.rs fn main() { tdlib_rs::build::check_features(); tdlib_rs::build::set_rerun_if(); tdlib_rs::build::build_local_tdlib(); } ``` ``` -------------------------------- ### Enable Static Linking for tdjson Source: https://github.com/federicobruzzone/tdlib-rs/blob/main/README.md Use this feature to enable static linking for `tdjson`. The final binary will not require `tdjson` to be installed in the target system runtime. This can be used with `download-tdlib` or `local-tdlib` features. ```toml [dependencies] tdlib-rs = { version = "...", features = ["download-tdlib", "static"] } ``` -------------------------------- ### Enable download-tdlib Feature in Cargo.toml Source: https://github.com/federicobruzzone/tdlib-rs/blob/main/README.md Use this configuration to enable the 'download-tdlib' feature, which downloads precompiled TDLib from GitHub releases. This avoids the need to manually compile and install TDLib on your system. ```toml [dependencies] tdlib = { version = "...", features = [ "download-tdlib" ] } [build-dependencies] tdlib = { version = "...", features = [ "download-tdlib" ] } ``` -------------------------------- ### Enable local-tdlib Feature in Cargo.toml Source: https://github.com/federicobruzzone/tdlib-rs/blob/main/README.md Configure Cargo.toml to use the 'local-tdlib' feature. This requires TDLib (version 1.8.61) to be compiled and installed on your system, with the LOCAL_TDLIB_PATH environment variable set. ```toml [dependencies] tdlib = { version = "...", features = [ "local-tdlib" ] } [build-dependencies] tdlib = { version = "...", features = [ "local-tdlib" ] } ``` -------------------------------- ### Unified Build Script Entry Point Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Provides the simplest configuration for the build.rs file using tdlib_rs::build::build. An optional destination path can be provided for the download-tdlib feature. ```rust // build.rs — simplest possible configuration fn main() { tdlib_rs::build::build(None); } ``` ```rust // build.rs — with a custom tdlib destination path (download-tdlib feature) fn main() { tdlib_rs::build::build(Some("/opt/myapp/tdlib".to_string())); } ``` -------------------------------- ### `tdlib_rs::build::build_download_tdlib` Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Downloads the precompiled TDLib binary for the current OS/arch from GitHub Releases and configures Cargo linker flags. Supports Linux, macOS, and Windows. Panics on unsupported platforms. ```APIDOC ## `tdlib_rs::build::build_download_tdlib` — Download and link TDLib automatically Downloads the precompiled TDLib binary for the current OS/arch from GitHub Releases and configures Cargo linker flags. Supports Linux x86_64/arm64, macOS x86_64/arm64, and Windows x86_64/arm64. Panics with a descriptive error if the platform is unsupported. ### Usage Add the following to your `Cargo.toml`: ```toml [dependencies] tdlib-rs = { version = "1.4.0", features = ["download-tdlib"] } [build-dependencies] tdlib-rs = { version = "1.4.0", features = ["download-tdlib"] } ``` In your `build.rs`: ```rust // build.rs fn main() { tdlib_rs::build::check_features(); tdlib_rs::build::set_rerun_if(); tdlib_rs::build::build_download_tdlib(None); // dest_path = None → TDLib extracted to Cargo's OUT_DIR // dest_path = Some("path") → also copied to that path } ``` ``` -------------------------------- ### Release New Version with Git Source: https://github.com/federicobruzzone/tdlib-rs/blob/main/RELEASE.md Use these git commands to add all changes, commit them with a release message, and push to the main branch. Then, delete all local tags, fetch tags from the remote, create a new tag for the release version, and push the new tag to the origin. ```bash git add --all git commit -sm "Release v1.0.0" git push origin main git tag -l | xargs git tag -d git fetch --tags git tag v1.0.0 git push origin v1.0.0 ``` -------------------------------- ### Link TDLib via pkg-config with tdlib-rs Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Use this method to link TDLib through `pkg-config`, which requires the `system-deps` crate. Ensure `PKG_CONFIG_PATH` and `LD_LIBRARY_PATH` are correctly set in your environment. This method is incompatible with the `static` feature flag. Enable the `pkg-config` feature. ```bash export PKG_CONFIG_PATH=$HOME/lib/tdlib/lib/pkgconfig/:$PKG_CONFIG_PATH export LD_LIBRARY_PATH=$HOME/lib/tdlib/lib/:$LD_LIBRARY_PATH ``` ```toml # Cargo.toml [dependencies] tdlib-rs = { version = "1.4.0", features = ["pkg-config"] } [build-dependencies] tdlib-rs = { version = "1.4.0", features = ["pkg-config"] } ``` ```rust // build.rs fn main() { tdlib_rs::build::check_features(); tdlib_rs::build::set_rerun_if(); tdlib_rs::build::build_pkg_config(); } ``` -------------------------------- ### Download and Link TDLib Automatically with tdlib-rs Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Use this snippet to automatically download precompiled TDLib binaries for supported platforms and link them. Ensure the `download-tdlib` feature is enabled in both `[dependencies]` and `[build-dependencies]` in Cargo.toml. ```toml # Cargo.toml [dependencies] tdlib-rs = { version = "1.4.0", features = ["download-tdlib"] } [build-dependencies] tdlib-rs = { version = "1.4.0", features = ["download-tdlib"] } ``` ```rust // build.rs fn main() { tdlib_rs::build::check_features(); tdlib_rs::build::set_rerun_if(); tdlib_rs::build::build_download_tdlib(None); // dest_path = None → TDLib extracted to Cargo's OUT_DIR // dest_path = Some("path") → also copied to that path } ``` -------------------------------- ### Build Script for download-tdlib Source: https://github.com/federicobruzzone/tdlib-rs/blob/main/README.md This build script utilizes the 'download-tdlib' feature. Ensure your Cargo.toml has the 'download-tdlib' feature enabled for both dependencies. ```rust // build.rs fn main() { tdlib_rs::build::build(None); } ``` -------------------------------- ### `tdlib_rs::build::build_pkg_config` Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Links TDLib via `pkg-config` using the `system-deps` crate. Requires `PKG_CONFIG_PATH` and `LD_LIBRARY_PATH` to be set correctly. Incompatible with the `static` feature flag. ```APIDOC ## `tdlib_rs::build::build_pkg_config` — Link TDLib via pkg-config Uses the `system-deps` crate to probe for TDLib through `pkg-config`. Requires `PKG_CONFIG_PATH` and `LD_LIBRARY_PATH` to be correctly set before building. Incompatible with the `static` feature flag. ### Usage Set the environment variables: ```bash export PKG_CONFIG_PATH=$HOME/lib/tdlib/lib/pkgconfig/:$PKG_CONFIG_PATH export LD_LIBRARY_PATH=$HOME/lib/tdlib/lib/:$LD_LIBRARY_PATH ``` Add the following to your `Cargo.toml`: ```toml [dependencies] tdlib-rs = { version = "1.4.0", features = ["pkg-config"] } [build-dependencies] tdlib-rs = { version = "1.4.0", features = ["pkg-config"] } ``` In your `build.rs`: ```rust // build.rs fn main() { tdlib_rs::build::check_features(); tdlib_rs::build::set_rerun_if(); tdlib_rs::build::build_pkg_config(); } ``` ``` -------------------------------- ### Create a TDLib client instance Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Instantiates a new TDLib client and returns its unique integer ID. This ID is required for all subsequent function calls and update polling for this client. At least one request must be sent before updates are delivered. ```rust use tdlib_rs; fn main() { // Create a TDLib client; returns a unique i32 client ID let client_id: i32 = tdlib_rs::create_client(); println!("Client created with id: {client_id}"); // client_id is passed to every functions::* call and to receive() } ``` -------------------------------- ### Configure TDLib client parameters Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Sets essential TDLib client parameters, including API credentials and database paths. This function is typically called in response to the `AuthorizationState::WaitTdlibParameters` update during the authorization process. ```rust use tdlib_rs::{functions, enums::AuthorizationState}; async fn configure_client(client_id: i32) { let result = functions::set_tdlib_parameters( false, // use_test_dc "my_app_db".into(), // database_directory String::new(), // files_directory String::new(), // database_encryption_key false, // use_file_database false, // use_chat_info_database false, // use_message_database false, // use_secret_chats 123456, // api_id (from https://my.telegram.org) "abcdef1234567890abcdef".into(), // api_hash "en".into(), // system_language_code "Desktop".into(), // device_model String::new(), // system_version "1.0.0".into(), // application_version client_id, ) .await; match result { Ok(_) => println!("TDLib parameters set successfully"), Err(e) => eprintln!("Error: {}", e.message), } } ``` -------------------------------- ### Static Linking with tdlib-rs Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Enables fully self-contained binaries by statically linking TDLib, OpenSSL, and zlib. This feature requires adding specific features to both dependencies and build-dependencies in Cargo.toml and calling `tdlib_rs::build::build(None)` in build.rs. ```toml # Cargo.toml [dependencies] tdlib-rs = { version = "1.4.0", features = ["download-tdlib", "static"] } [build-dependencies] tdlib-rs = { version = "1.4.0", features = ["download-tdlib", "static"] } ``` ```rust // build.rs fn main() { // Automatically downloads TDLib and statically links all components. // Panics at build time if any required static library (.a / .lib) is missing. tdlib_rs::build::build(None); } ``` -------------------------------- ### tdlib_rs::create_client Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Creates and registers a new TDLib client, returning its integer client ID. Multiple independent clients can coexist within the same process. ```APIDOC ## `tdlib_rs::create_client` — Create a TDLib client instance Creates and registers a new TDLib client, returning its integer client ID. At least one request must be sent to the client before it begins delivering updates. Multiple independent clients can coexist within the same process. ### Usage ```rust use tdlib_rs; fn main() { // Create a TDLib client; returns a unique i32 client ID let client_id: i32 = tdlib_rs::create_client(); println!("Client created with id: {client_id}"); // client_id is passed to every functions::* call and to receive() } ``` ``` -------------------------------- ### Submit Phone Number for Login Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Call this function when TDLib is in the `AuthorizationState::WaitPhoneNumber` state. It sends the user's phone number to initiate the authentication process. TDLib will then transition to `AuthorizationState::WaitCode` or `AuthorizationState::WaitOtherDeviceConfirmation`. ```rust use tdlib_rs::functions; async fn submit_phone(client_id: i32) { loop { let phone = "+15551234567".to_string(); match functions::set_authentication_phone_number(phone, None, client_id).await { Ok(_) => { println!("Phone number accepted, waiting for code..."); break; } Err(e) => { eprintln!("Invalid phone number: {}", e.message); // retry with corrected input break; } } } } ``` -------------------------------- ### Submit 2FA Password Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt This function is required for accounts with two-factor authentication enabled. Call it when TDLib enters the `AuthorizationState::WaitPassword` state, providing the cloud password. It verifies the password and proceeds with the authorization. ```rust use tdlib_rs::functions; async fn submit_2fa_password(client_id: i32, password: String) { match functions::check_authentication_password(password, client_id).await { Ok(_) => println!("2FA password accepted"), Err(e) => eprintln!("Wrong password: {}", e.message), } } ``` -------------------------------- ### functions::set_tdlib_parameters Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Configures the TDLib client with all required parameters including the Telegram API credentials, database paths, and application metadata. This must be called in response to the `AuthorizationState::WaitTdlibParameters` update during the authorization flow. ```APIDOC ## `functions::set_tdlib_parameters` — Configure TDLib client parameters Configures the TDLib client with all required parameters including the Telegram API credentials, database paths, and application metadata. This must be called in response to the `AuthorizationState::WaitTdlibParameters` update during the authorization flow. ### Parameters - **use_test_dc** (bool) - Required - Whether to use test datacenter. - **database_directory** (string) - Required - Path to the directory for database files. - **files_directory** (string) - Required - Path to the directory for storing files. - **database_encryption_key** (string) - Optional - Secret key for database encryption, if needed. - **use_file_database** (bool) - Required - Whether to use the file database. - **use_chat_info_database** (bool) - Required - Whether to use the chat info database. - **use_message_database** (bool) - Required - Whether to use the message database. - **use_secret_chats** (bool) - Required - Whether to use secret chats. - **api_id** (i32) - Required - Your Telegram API ID (from https://my.telegram.org). - **api_hash** (string) - Required - Your Telegram API Hash (from https://my.telegram.org). - **system_language_code** (string) - Required - System language code (e.g., "en"). - **device_model** (string) - Required - Model of the device (e.g., "Desktop"). - **system_version** (string) - Required - Version of the system (e.g., "10.15.7"). - **application_version** (string) - Required - Version of the application (e.g., "1.0.0"). - **client_id** (i32) - Required - The ID of the client to configure. ### Usage ```rust use tdlib_rs::{functions, enums::AuthorizationState}; async fn configure_client(client_id: i32) { let result = functions::set_tdlib_parameters( false, // use_test_dc "my_app_db".into(), // database_directory String::new(), // files_directory String::new(), // database_encryption_key false, // use_file_database false, // use_chat_info_database false, // use_message_database false, // use_secret_chats 123456, // api_id (from https://my.telegram.org) "abcdef1234567890abcdef".into(), // api_hash "en".into(), // system_language_code "Desktop".into(), // device_model String::new(), // system_version "1.0.0".into(), // application_version client_id, ) .await; match result { Ok(_) => println!("TDLib parameters set successfully"), Err(e) => eprintln!("Error: {}", e.message), } } ``` ``` -------------------------------- ### Parse TDLib TL Definitions (Type and Function) Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Parses individual TDLib Type Language definition strings into `Definition` structs. Handles both type constructors and function definitions. Ensure correct context for function parsing. ```rust use tdlib_rs_parser::tl::{Definition, Category}; fn main() { // Parse a type definition let type_def: Definition = "message id:int53 text:string = Message" .parse() .expect("Failed to parse definition"); assert_eq!(type_def.name, "message"); assert_eq!(type_def.params.len(), 2); assert_eq!(type_def.category, Category::Types); println!("Type: {}", type_def.ty.name); // "Message" // Parse a function definition (in ---functions--- section context, category set externally) let func_def: Definition = "sendMessage chat_id:int53 text:string = Message" .parse() .unwrap(); println!("Function: {} -> {}", func_def.name, func_def.ty); println!("Round-trip: {}", func_def); // "sendMessage chat_id:int53 text:string = Message" // Parse errors use tdlib_rs_parser::errors::ParseError; assert_eq!("".parse::(), Err(ParseError::Empty)); assert_eq!("noequals".parse::(), Err(ParseError::MissingType)); } ``` -------------------------------- ### Register New Telegram Account Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt This function is used when TDLib is in the `AuthorizationState::WaitRegistration` state. It registers a new Telegram account by providing the user's first name, last name, and acceptance of the terms of service. ```rust use tdlib_rs::functions; async fn register_new_user(client_id: i32) { functions::register_user( "Alice".to_string(), // first_name "Smith".to_string(), // last_name false, // disable_notification client_id, ) .await .expect("Failed to register user"); } ``` -------------------------------- ### Retrieve Current Authenticated User Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Call `get_me` after the authorization state is `AuthorizationState::Ready` to fetch the profile information of the currently logged-in user. The result is a `User` enum, typically containing a `types::User` struct with details like name, ID, and phone number. ```rust use tdlib_rs::{functions, enums::User}; #[tokio::main] async fn main() { let client_id = tdlib_rs::create_client(); // ... perform full authorization flow first ... match functions::get_me(client_id).await { Ok(User::User(me)) => { println!("Logged in as: {} {} (id: {})", me.first_name, me.last_name, me.id); println!("Phone: {}", me.phone_number); } Err(e) => eprintln!("get_me failed: {}", e.message), } } ``` -------------------------------- ### Verify Authentication Code Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Use this function to submit the verification code received via SMS or another Telegram client. It is called when TDLib is in the `AuthorizationState::WaitCode` state. Successful verification leads to `AuthorizationState::Ready` or `AuthorizationState::WaitPassword` for accounts with 2FA enabled. ```rust use tdlib_rs::functions; async fn verify_code(client_id: i32, code: String) { match functions::check_authentication_code(code, client_id).await { Ok(_) => println!("Code verified, authorization complete (or awaiting 2FA password)"), Err(e) => eprintln!("Code verification failed: {}", e.message), } } ``` -------------------------------- ### functions::get_me Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Retrieves information about the currently authenticated user. This function returns a `User` enum, which typically wraps a `types::User` struct containing details such as the user's ID, names, and phone number. It must only be called after the client has reached the `AuthorizationState::Ready` state. ```APIDOC ## `functions::get_me` — Retrieve the current authenticated user Returns a `User` enum wrapping a `types::User` struct containing the authenticated account's profile information (ID, names, phone, etc.). Must only be called after `AuthorizationState::Ready`. ### Parameters - `client_id` (integer) - The identifier of the TDLib client. ### Response #### Success Response (200) - `User` (enum) - An enum that can be `User::User` containing a `types::User` struct with user details. ### Request Example ```rust use tdlib_rs::{functions, enums::User}; #[tokio::main] async fn main() { let client_id = tdlib_rs::create_client(); // ... perform full authorization flow first ... match functions::get_me(client_id).await { Ok(User::User(me)) => { println!("Logged in as: {} {} (id: {})", me.first_name, me.last_name, me.id); println!("Phone: {}", me.phone_number); } Err(e) => eprintln!("get_me failed: {}", e.message), } } ``` ``` -------------------------------- ### Gracefully Close TDLib Client Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Initiates the graceful closure of a TDLib client. After calling `functions::close`, the client will transition through `AuthorizationState::Closing` to `AuthorizationState::Closed`. It is important to wait for the `Closed` state before terminating the receive loop. ```rust use tdlib_rs::{functions, enums::{Update, AuthorizationState}}; async fn shutdown(client_id: i32) { functions::close(client_id) .await .expect("Failed to initiate close"); // Continue polling until Closed state is received loop { if let Some((Update::AuthorizationState(s), _)) = tdlib_rs::receive() { if matches!(s.authorization_state, AuthorizationState::Closed) { println!("Client closed cleanly."); break; } } } } ``` -------------------------------- ### Verify Email Authentication Code Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Call this function when TDLib is in the `AuthorizationState::WaitEmailCode` state. It requires wrapping the email verification code within the `EmailAddressAuthentication::Code` enum variant before submission. ```rust use tdlib_rs::{functions, enums, types}; async fn verify_email_code(client_id: i32, code: String) { let auth_code = enums::EmailAddressAuthentication::Code( types::EmailAddressAuthenticationCode { code }, ); match functions::check_authentication_email_code(auth_code, client_id).await { Ok(_) => println!("Email code verified"), Err(e) => eprintln!("Error: {}", e.message), } } ``` -------------------------------- ### Parse TDLib Type Language (.tl) File Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Parses a TDLib schema file (`.tl`) into a collection of `Definition` objects. It filters out `ParseError::NotImplemented` and other errors, printing them to stderr. Useful for code generation or schema analysis. ```rust use std::fs; use tdlib_rs_parser::{parse_tl_file, tl::Definition}; use tdlib_rs_parser::errors::ParseError; fn main() -> std::io::Result<()> { let contents = fs::read_to_string("tdlib-rs/tl/api.tl")?; let definitions: Vec = parse_tl_file(contents) .filter_map(|result| match result { Ok(def) => Some(def), Err(ParseError::NotImplemented) => None, // skip unimplemented constructs Err(e) => { eprintln!("Parse error: {e:?}"); None } }) .collect(); println!("Parsed {} TL definitions", definitions.len()); // Inspect the first definition if let Some(first) = definitions.first() { println!("Name: {}", first.name); println!("Description: {}", first.description); println!("Params: {}", first.params.len()); println!("Type: {}", first.ty); println!("Category: {:?}", first.category); } Ok(()) } ``` -------------------------------- ### Parse TDLib TL Parameters Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Parses parameter strings in `name:type` format into `Parameter` structs. Supports simple and generic types. Handles parsing errors for empty names or invalid generic types. ```rust use tdlib_rs_parser::tl::{Parameter, Type}; use tdlib_rs_parser::errors::ParamParseError; fn main() { // Parse a simple parameter let param: Parameter = "chat_id:int53".parse().expect("Invalid parameter"); assert_eq!(param.name, "chat_id"); assert_eq!(param.ty.name, "int53"); assert!(param.ty.bare); // lowercase first char → bare type println!("Param: {param}"); // "chat_id:int53" // Parse a generic parameter let vec_param: Parameter = "messages:Vector".parse().unwrap(); assert_eq!(vec_param.ty.name, "Vector"); assert!(vec_param.ty.generic_arg.is_some()); // Parse errors assert_eq!(":noname".parse::(), Err(ParamParseError::Empty)); assert_eq!("foo:(), Err(ParamParseError::InvalidGeneric)); assert_eq!("nocolon".parse::(), Err(ParamParseError::NotImplemented)); } ``` -------------------------------- ### Include Telegram Bot API Extensions Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Enables the generation of TDLib functions and parameters exclusively for Telegram bot accounts. This feature is activated by the `bots-only-api` flag in Cargo.toml. ```toml # Cargo.toml [dependencies] tdlib-rs = { version = "1.4.0", features = ["download-tdlib", "bots-only-api"] } [build-dependencies] tdlib-rs = { version = "1.4.0", features = ["download-tdlib"] } ``` ```rust // With bots-only-api enabled, bot-exclusive functions are available: use tdlib_rs::functions; #[tokio::main] async fn main() { let client_id = tdlib_rs::create_client(); // ... authorize as a bot using bot token ... // Bot-only functions like answerCallbackQuery, sendInvoice, etc. // are available in the generated functions module. functions::set_log_verbosity_level(1, client_id).await.unwrap(); } ``` -------------------------------- ### Generate Rust Bindings from TL Definitions Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Generates Rust source code for types, enums, and functions from parsed TL definitions. The `gen_bots_only_api` flag controls the inclusion of bot-exclusive API surface. ```rust use std::io::BufWriter; use tdlib_rs_gen::generate_rust_code; use tdlib_rs_parser::{parse_tl_file, tl::Definition}; fn main() -> std::io::Result<()> { let tl_contents = std::fs::read_to_string("tdlib-rs/tl/api.tl")?; let definitions: Vec = parse_tl_file(tl_contents) .filter_map(|r| r.ok()) .collect(); // Write generated Rust code to stdout let stdout = std::io::stdout(); let mut writer = BufWriter::new(stdout.lock()); // false = omit bot-only API; true = include bot-only API generate_rust_code(&mut writer, &definitions, false)?; writer.flush()?; // Output contains: // pub mod types { pub struct Message { ... } ... } // pub mod enums { pub enum Update { ... } ... } // pub mod functions { pub async fn get_me(client_id: i32) -> Result<...> { ... } ... } Ok(()) } ``` -------------------------------- ### `tdlib_rs::build::check_features` Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Validates mutually exclusive feature flags for tdlib-rs to prevent build conflicts. Emits `compile_error!` if incompatible features are enabled simultaneously. ```APIDOC ## `tdlib_rs::build::check_features` — Validate mutually exclusive feature flags Emits `compile_error!` if incompatible features are enabled simultaneously. The following pairs are mutually exclusive: `(docs, pkg-config)`, `(docs, download-tdlib)`, `(docs, local-tdlib)`, `(pkg-config, local-tdlib)`, `(pkg-config, download-tdlib)`, `(static, pkg-config)`, `(local-tdlib, download-tdlib)`. Called automatically by `build()`. ### Usage This function is typically called automatically within the build process. However, if you are using a custom build script, you can call it explicitly: ```rust // build.rs — called explicitly for custom build scripts fn main() { tdlib_rs::build::check_features(); // compile error if feature conflict detected tdlib_rs::build::set_rerun_if(); // custom logic... tdlib_rs::build::build_download_tdlib(None); } ``` ``` -------------------------------- ### Poll for TDLib updates and responses Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Polls TDLib for new updates with a specified timeout. Returns an `Option<(Update, client_id)>`. Responses to internal requests are handled by the observer pattern; this function primarily yields unsolicited server updates. ```rust use tdlib_rs::{self, enums::Update}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; let client_id = tdlib_rs::create_client(); let running = Arc::new(AtomicBool::new(true)); let running_clone = running.clone(); // Spawn a blocking thread (or use spawn_blocking in Tokio) to poll updates std::thread::spawn(move || { while running_clone.load(Ordering::Acquire) { if let Some((update, cid)) = tdlib_rs::receive() { match update { Update::AuthorizationState(auth) => { println!("Client {cid}: auth state changed: {:?}", auth.authorization_state); } Update::NewMessage(msg) => { println!("New message on client {cid}: {:?}", msg.message); } _ => {} } } } }); ``` -------------------------------- ### Set TDLib log verbosity level Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Configures the verbosity of TDLib's internal logging. Level 0 is for fatal errors only, while level 5 provides extensive debug output. This function must be called with an active client ID to initiate the TDLib event loop for that client. ```rust use tdlib_rs::functions; #[tokio::main] async fn main() { let client_id = tdlib_rs::create_client(); // Level 2 = warnings and errors; triggers initial client event loop start functions::set_log_verbosity_level(2, client_id) .await .expect("Failed to set log verbosity"); } ``` -------------------------------- ### functions::check_authentication_password Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Submits the two-factor authentication (cloud password) when the client is in the `AuthorizationState::WaitPassword` state. This function is only required for accounts that have two-factor authentication enabled. ```APIDOC ## `functions::check_authentication_password` — Submit 2FA password Submits the two-factor authentication (cloud password) when `AuthorizationState::WaitPassword` is received. Required only for accounts with 2FA enabled. ### Parameters - `password` (string) - The two-factor authentication password. - `client_id` (integer) - The identifier of the TDLib client. ### Request Example ```rust use tdlib_rs::functions; async fn submit_2fa_password(client_id: i32, password: String) { match functions::check_authentication_password(password, client_id).await { Ok(_) => println!("2FA password accepted"), Err(e) => eprintln!("Wrong password: {}", e.message), } } ``` ``` -------------------------------- ### functions::close Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Gracefully closes a TDLib client. This function initiates the closing process, during which the client's authorization state transitions through `AuthorizationState::Closing` and finally to `AuthorizationState::Closed`. Callers should continue to poll for updates and wait for the `Closed` state before terminating their receive loop. ```APIDOC ## `functions::close` — Gracefully close a TDLib client Requests TDLib to close the specified client. The client transitions through `AuthorizationState::Closing` and then `AuthorizationState::Closed`. Callers should wait for the `Closed` state before terminating the receive loop. ### Parameters - `client_id` (integer) - The identifier of the TDLib client to close. ### Request Example ```rust use tdlib_rs::{functions, enums::{Update, AuthorizationState}}; async fn shutdown(client_id: i32) { functions::close(client_id) .await .expect("Failed to initiate close"); // Continue polling until Closed state is received loop { if let Some((Update::AuthorizationState(s), _)) = tdlib_rs::receive() { if matches!(s.authorization_state, AuthorizationState::Closed) { println!("Client closed cleanly."); break; } } } } ``` ``` -------------------------------- ### Parse TDLib TL Types Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Parses type descriptors in `name` or `name` format into `Type` structs. Distinguishes between bare (concrete) and boxed (abstract) types, and handles nested generics. Includes error cases for empty strings and invalid generic syntax. ```rust use tdlib_rs_parser::tl::Type; use tdlib_rs_parser::errors::ParamParseError; fn main() { // Bare (concrete) type let bare: Type = "int53".parse().unwrap(); assert!(bare.bare); assert_eq!(bare.name, "int53"); assert!(bare.generic_arg.is_none()); // Boxed (abstract) type let boxed: Type = "Message".parse().unwrap(); assert!(!boxed.bare); // Generic type: Vector let generic: Type = "Vector".parse().unwrap(); assert_eq!(generic.name, "Vector"); let arg = generic.generic_arg.as_ref().unwrap(); assert_eq!(arg.name, "Message"); // Nested generics: vector> let nested: Type = "vector>".parse().unwrap(); println!("Nested: {nested}"); // "vector>" // Error cases assert_eq!("".parse::(), Err(ParamParseError::Empty)); assert_eq!("foo(), Err(ParamParseError::InvalidGeneric)); } ``` -------------------------------- ### tdlib_rs::receive Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Polls TDLib with a 2-second timeout, returning the next available `(Update, client_id)` pair if an unsolicited update is available, or `None` if there is nothing to receive. Responses to outbound requests are intercepted internally by the `Observer` and resolved through the corresponding async function's `Future`; only unprompted server updates reach this function. ```APIDOC ## `tdlib_rs::receive` — Poll for updates and responses Polls TDLib with a 2-second timeout, returning the next available `(Update, client_id)` pair if an unsolicited update is available, or `None` if there is nothing to receive. Responses to outbound requests are intercepted internally by the `Observer` and resolved through the corresponding async function's `Future`; only unprompted server updates reach this function. ### Usage ```rust use tdlib_rs::{self, enums::Update}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; let client_id = tdlib_rs::create_client(); let running = Arc::new(AtomicBool::new(true)); let running_clone = running.clone(); // Spawn a blocking thread (or use spawn_blocking in Tokio) to poll updates std::thread::spawn(move || { while running_clone.load(Ordering::Acquire) { if let Some((update, cid)) = tdlib_rs::receive() { match update { Update::AuthorizationState(auth) => { println!("Client {cid}: auth state changed: {:?}", auth.authorization_state); } Update::NewMessage(msg) => { println!("New message on client {cid}: {:?}", msg.message); } _ => {} } } } }); ``` ``` -------------------------------- ### functions::register_user Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Registers a new Telegram account. This function is called when TDLib is in the `AuthorizationState::WaitRegistration` state, indicating that the provided phone number is not yet associated with an account. It requires the user's first name, last name, and an option to disable notifications. ```APIDOC ## `functions::register_user` — Register a new Telegram account Called when `AuthorizationState::WaitRegistration` is received, indicating the phone number is not yet associated with an account. Provides first name, last name, and ToS acceptance. ### Parameters - `first_name` (string) - The first name of the user. - `last_name` (string) - The last name of the user. - `disable_notification` (boolean) - If true, notifications for new chats are disabled. - `client_id` (integer) - The identifier of the TDLib client. ### Request Example ```rust use tdlib_rs::functions; async fn register_new_user(client_id: i32) { functions::register_user( "Alice".to_string(), // first_name "Smith".to_string(), // last_name false, // disable_notification client_id, ) .await .expect("Failed to register user"); } ``` ``` -------------------------------- ### Enable Bots-Only API Generation Source: https://github.com/federicobruzzone/tdlib-rs/blob/main/README.md This feature enables the generation of functions that are exclusively used by Telegram bots. ```toml [dependencies] tdlib-rs = { version = "...", features = ["bots-only-api"] } ``` -------------------------------- ### functions::check_authentication_code Source: https://context7.com/federicobruzzone/tdlib-rs/llms.txt Verifies the authentication code received via SMS or another Telegram client. This function is invoked when TDLib is in the `AuthorizationState::WaitCode` state. Successful verification transitions the client to `AuthorizationState::Ready` or `AuthorizationState::WaitPassword` if two-factor authentication is enabled. ```APIDOC ## `functions::check_authentication_code` — Verify the SMS/Telegram code Submits the verification code received via SMS or another Telegram client. Called in response to `AuthorizationState::WaitCode`. On success, transitions to `AuthorizationState::Ready` (or `WaitPassword` for 2FA accounts). ### Parameters - `code` (string) - The authentication code received. - `client_id` (integer) - The identifier of the TDLib client. ### Request Example ```rust use tdlib_rs::functions; async fn verify_code(client_id: i32, code: String) { match functions::check_authentication_code(code, client_id).await { Ok(_) => println!("Code verified, authorization complete (or awaiting 2FA password)"), Err(e) => eprintln!("Code verification failed: {}", e.message), } } ``` ```