tdlib_rs/
lib.rs

1// Copyright 2020 - developers of the `grammers` project.
2// Copyright 2021 - developers of the `tdlib-rs` project.
3// Copyright 2024 - developers of the `tgt` and `tdlib-rs` projects.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10pub mod build;
11mod generated;
12mod observer;
13mod tdjson;
14
15pub use generated::{enums, functions, types};
16
17use enums::Update;
18use once_cell::sync::Lazy;
19use serde_json::Value;
20use std::sync::atomic::{AtomicU32, Ordering};
21
22static EXTRA_COUNTER: AtomicU32 = AtomicU32::new(0);
23static OBSERVER: Lazy<observer::Observer> = Lazy::new(observer::Observer::new);
24
25/// Create a TdLib client returning its id. Note that to start receiving
26/// updates for a client you need to send at least a request with it first.
27pub fn create_client() -> i32 {
28    tdjson::create_client()
29}
30
31/// Receive a single update or response from TdLib. If it's an update, it
32/// returns a tuple with the `Update` and the associated `client_id`.
33/// Note that to start receiving updates for a client you need to send
34/// at least a request with it first.
35pub fn receive() -> Option<(Update, i32)> {
36    let response = tdjson::receive(2.0);
37    if let Some(response_str) = response {
38        let response: Value = serde_json::from_str(&response_str).unwrap();
39
40        match response.get("@extra") {
41            Some(_) => {
42                OBSERVER.notify(response);
43            }
44            None => {
45                let client_id = response["@client_id"].as_i64().unwrap() as i32;
46                match serde_json::from_value(response) {
47                    Ok(update) => {
48                        return Some((update, client_id));
49                    }
50                    Err(e) => {
51                        log::warn!(
52                            "Received an unknown response: {}\nReason: {}",
53                            response_str,
54                            e
55                        );
56                    }
57                }
58            }
59        }
60    }
61
62    None
63}
64
65pub(crate) async fn send_request(client_id: i32, mut request: Value) -> Value {
66    let extra = EXTRA_COUNTER.fetch_add(1, Ordering::Relaxed);
67    request["@extra"] = serde_json::to_value(extra).unwrap();
68
69    let receiver = OBSERVER.subscribe(extra);
70    tdjson::send(client_id, request.to_string());
71
72    receiver.await.unwrap()
73}