rtdlib_sys/
lib.rs

1extern crate libc;
2
3use libc::{c_double, c_int, c_long, c_void};
4use std::ffi::CStr;
5use std::ffi::CString;
6use std::os::raw::c_char;
7use std::ptr;
8
9type TdlibClient = *mut c_void;
10
11#[derive(Debug)]
12pub struct Tdlib {
13  instance: TdlibClient,
14}
15
16unsafe impl Send for Tdlib {}
17unsafe impl Sync for Tdlib {}
18
19#[link(name = "tdjson")]
20extern "C" {
21  fn td_json_client_create() -> TdlibClient;
22  fn td_json_client_send(client: TdlibClient, request: *const c_char);
23  fn td_json_client_receive(client: TdlibClient, timeout: c_double) -> *mut c_char;
24  fn td_json_client_execute(client: TdlibClient, request: *const c_char) -> *mut c_char;
25  fn td_json_client_destroy(client: TdlibClient);
26
27  fn td_set_log_verbosity_level(level: c_int);
28  fn td_set_log_file_path(path: *const c_char) -> c_int;
29  fn td_set_log_max_file_size(size: c_long);
30}
31
32impl Tdlib {
33  /// Sets the verbosity level of the internal logging of TDLib.
34  ///
35  /// By default the TDLib uses a log verbosity level of 5.
36  ///
37  /// # Parameters
38  ///
39  /// `level` New value of logging verbosity level. Value 0 corresponds to fatal errors,
40  /// value 1 corresponds to errors, value 2 corresponds to warnings and debug warnings,
41  /// value 3 corresponds to informational, value 4 corresponds to debug, value 5 corresponds
42  /// to verbose debug, value greater than 5 and up to 1024 can be used to enable even more logging.
43  ///
44  /// # Examples
45  ///
46  /// ```
47  /// use rtdlib_sys::Tdlib;
48  /// Tdlib::set_log_verbosity_level(3);
49  /// ```
50  pub fn set_log_verbosity_level<'a>(level: i32) -> Result<(), &'a str> {
51    if level < 0 {
52      Err("log verbosity level should be >= 0")
53    } else if level > 1024 {
54      Err("log verbosity level should be <= 1024")
55    } else {
56      unsafe { td_set_log_verbosity_level(level) };
57      Ok(())
58    }
59  }
60
61  /// Sets maximum size of the file to where the internal TDLib log is written before the file will be auto-rotated.
62  ///
63  /// Unused if log is not written to a file. Defaults to 10 MB.
64  ///
65  /// # Parameters
66  ///
67  /// `size` Maximum size of the file to where the internal TDLib log is written before the file will be auto-rotated. Should be positive.
68  ///
69  /// # Examples
70  ///
71  /// ```
72  /// use rtdlib_sys::Tdlib;
73  /// Tdlib::set_log_max_file_size(1024 * 1024);
74  /// ```
75  pub fn set_log_max_file_size(size: i64) {
76    unsafe { td_set_log_max_file_size(size as c_long) };
77  }
78
79  /// Sets the path to the file where the internal TDLib log will be written.
80  ///
81  /// By default TDLib writes logs to stderr or an OS specific log. Use this method to write the log to a file instead.
82  ///
83  /// # Parameters
84  ///
85  /// `path` Maybe path to a file where the internal TDLib log will be written. Use `None` to switch back to the default logging behaviour.
86  ///
87  /// # Examples
88  ///
89  /// ```
90  /// use rtdlib_sys::Tdlib;
91  /// Tdlib::set_log_file_path(Some("/var/log/tdlib/tdlib.log"));
92  /// ```
93  pub fn set_log_file_path(path: Option<&str>) -> bool {
94    let result = match path {
95      None => unsafe { td_set_log_file_path(ptr::null()) },
96      Some(path_) => {
97        let cpath = CString::new(path_).unwrap();
98        unsafe { td_set_log_file_path(cpath.as_ptr()) }
99      }
100    };
101    match result {
102      1 => true,
103      0 => false,
104      _ => panic!("unexpected response from libtdjson: {:?}", result)
105    }
106  }
107
108  /// Creates a new instance of TDLib.
109  ///
110  /// # Examples
111  ///
112  /// ```
113  /// use rtdlib_sys::Tdlib;
114  /// let tdlib = Tdlib::new();
115  /// ```
116  pub fn new() -> Self {
117    let client = unsafe { td_json_client_create() };
118    Tdlib { instance: client }
119  }
120
121  /// Sends request to the TDLib client.
122  ///
123  /// May be called from any thread.
124  ///
125  /// # Examples
126  ///
127  /// ```
128  /// use rtdlib_sys::Tdlib;
129  /// let tdlib = Tdlib::new();
130  /// let request = r#"{"@type": "getMe"}"#;
131  /// tdlib.send(request);
132  /// ```
133  pub fn send(&self, request: &str) {
134    let cstring = CString::new(request).unwrap();
135    unsafe { td_json_client_send(self.instance, cstring.as_ptr()) }
136  }
137
138  /// Synchronously executes TDLib request.
139  ///
140  /// May be called from any thread. Only a few requests can be executed synchronously.
141  ///
142  /// # Examples
143  ///
144  /// ```
145  /// use rtdlib_sys::Tdlib;
146  /// let tdlib = Tdlib::new();
147  /// let request = r#"{"@type": "getTextEntities", "text": "@telegram /test_command https://telegram.org telegram.me"}"#;
148  /// tdlib.execute(request);
149  /// ```
150  pub fn execute(&self, request: &str) -> Option<String> {
151    let cstring = CString::new(request).unwrap();
152    let result = unsafe {
153      td_json_client_execute(self.instance, cstring.as_ptr())
154        .as_ref()
155        .map(|response| CStr::from_ptr(response).to_string_lossy().into_owned())
156    };
157    result
158  }
159
160  /// Receives incoming updates and request responses from the TDLib client.
161  ///
162  /// May be called from any thread, but shouldn't be called simultaneously
163  /// from two different threads.
164  ///
165  /// # Examples
166  ///
167  /// ```
168  /// use rtdlib_sys::Tdlib;
169  /// let tdlib = Tdlib::new();
170  /// tdlib.receive(5.0);
171  /// ```
172  pub fn receive(&self, timeout: f64) -> Option<String> {
173//    debug!("tdlib receive with timeout {}s", timeout);
174    unsafe {
175      match td_json_client_receive(self.instance, timeout)
176        .as_ref()
177        .map(|response| CStr::from_ptr(response).to_string_lossy().into_owned()) {
178        None => {
179          None
180        }
181        Some(contents) => {
182          Some(contents)
183        }
184      }
185    }
186  }
187}
188
189impl Drop for Tdlib {
190  fn drop(&mut self) {
191    unsafe {
192      td_json_client_destroy(self.instance);
193    }
194  }
195}