telegram_webapp_sdk/api/
user.rs

1use js_sys::{Function, Reflect};
2use wasm_bindgen::{JsCast, prelude::*};
3use web_sys::window;
4
5/// Calls `Telegram.WebApp.requestContact()`.
6///
7/// Requires the user's explicit permission to share their contact information.
8///
9/// # Errors
10/// Returns `Err(JsValue)` if `Telegram.WebApp` or the method is unavailable, or
11/// if the call fails.
12///
13/// # Examples
14/// ```no_run
15/// use telegram_webapp_sdk::api::user::request_contact;
16///
17/// let _ = request_contact();
18/// ```
19pub fn request_contact() -> Result<(), JsValue> {
20    let webapp = webapp_object()?;
21    let func =
22        Reflect::get(&webapp, &JsValue::from_str("requestContact"))?.dyn_into::<Function>()?;
23    func.call0(&webapp)?;
24    Ok(())
25}
26
27/// Calls `Telegram.WebApp.requestPhoneNumber()`.
28///
29/// Requires the user's explicit permission to share their phone number.
30///
31/// # Errors
32/// Returns `Err(JsValue)` if `Telegram.WebApp` or the method is unavailable, or
33/// if the call fails.
34///
35/// # Examples
36/// ```no_run
37/// use telegram_webapp_sdk::api::user::request_phone_number;
38///
39/// let _ = request_phone_number();
40/// ```
41pub fn request_phone_number() -> Result<(), JsValue> {
42    let webapp = webapp_object()?;
43    let func =
44        Reflect::get(&webapp, &JsValue::from_str("requestPhoneNumber"))?.dyn_into::<Function>()?;
45    func.call0(&webapp)?;
46    Ok(())
47}
48
49/// Calls `Telegram.WebApp.openContact()`.
50///
51/// Requires the user's permission to open the contact interface in Telegram.
52///
53/// # Errors
54/// Returns `Err(JsValue)` if `Telegram.WebApp` or the method is unavailable, or
55/// if the call fails.
56///
57/// # Examples
58/// ```no_run
59/// use telegram_webapp_sdk::api::user::open_contact;
60///
61/// let _ = open_contact();
62/// ```
63pub fn open_contact() -> Result<(), JsValue> {
64    let webapp = webapp_object()?;
65    let func = Reflect::get(&webapp, &JsValue::from_str("openContact"))?.dyn_into::<Function>()?;
66    func.call0(&webapp)?;
67    Ok(())
68}
69
70fn webapp_object() -> Result<JsValue, JsValue> {
71    let win = window().ok_or_else(|| JsValue::from_str("no window"))?;
72    let tg = Reflect::get(&win, &JsValue::from_str("Telegram"))?;
73    Reflect::get(&tg, &JsValue::from_str("WebApp"))
74}
75
76#[cfg(test)]
77mod tests {
78    use js_sys::{Function, Object, Reflect};
79    use wasm_bindgen_test::{wasm_bindgen_test, wasm_bindgen_test_configure};
80    use web_sys::window;
81
82    use super::*;
83
84    wasm_bindgen_test_configure!(run_in_browser);
85
86    #[allow(dead_code)]
87    fn setup_webapp() -> Object {
88        let win = window().unwrap();
89        let telegram = Object::new();
90        let webapp = Object::new();
91        let _ = Reflect::set(&win, &"Telegram".into(), &telegram);
92        let _ = Reflect::set(&telegram, &"WebApp".into(), &webapp);
93        webapp
94    }
95
96    #[wasm_bindgen_test]
97    #[allow(dead_code, clippy::unused_unit)]
98    fn request_contact_ok() {
99        let webapp = setup_webapp();
100        let func = Function::new_no_args("this.called = true;");
101        let _ = Reflect::set(&webapp, &"requestContact".into(), &func);
102        assert!(request_contact().is_ok());
103        assert!(
104            Reflect::get(&webapp, &"called".into())
105                .unwrap()
106                .as_bool()
107                .unwrap()
108        );
109    }
110
111    #[wasm_bindgen_test]
112    #[allow(dead_code, clippy::unused_unit)]
113    fn request_contact_err() {
114        let _ = setup_webapp();
115        assert!(request_contact().is_err());
116    }
117
118    #[wasm_bindgen_test]
119    #[allow(dead_code, clippy::unused_unit)]
120    fn request_phone_number_ok() {
121        let webapp = setup_webapp();
122        let func = Function::new_no_args("this.called = true;");
123        let _ = Reflect::set(&webapp, &"requestPhoneNumber".into(), &func);
124        assert!(request_phone_number().is_ok());
125        assert!(
126            Reflect::get(&webapp, &"called".into())
127                .unwrap()
128                .as_bool()
129                .unwrap()
130        );
131    }
132
133    #[wasm_bindgen_test]
134    #[allow(dead_code, clippy::unused_unit)]
135    fn request_phone_number_err() {
136        let _ = setup_webapp();
137        assert!(request_phone_number().is_err());
138    }
139
140    #[wasm_bindgen_test]
141    #[allow(dead_code, clippy::unused_unit)]
142    fn open_contact_ok() {
143        let webapp = setup_webapp();
144        let func = Function::new_no_args("this.called = true;");
145        let _ = Reflect::set(&webapp, &"openContact".into(), &func);
146        assert!(open_contact().is_ok());
147        assert!(
148            Reflect::get(&webapp, &"called".into())
149                .unwrap()
150                .as_bool()
151                .unwrap()
152        );
153    }
154
155    #[wasm_bindgen_test]
156    #[allow(dead_code, clippy::unused_unit)]
157    fn open_contact_err() {
158        let _ = setup_webapp();
159        assert!(open_contact().is_err());
160    }
161}