telegram_webapp_sdk/core/
init.rs

1use js_sys::Reflect;
2use serde_wasm_bindgen::from_value;
3use wasm_bindgen::JsValue;
4use web_sys::window;
5
6use crate::core::{
7    context::TelegramContext,
8    types::{
9        chat::TelegramChat, init_data::TelegramInitData,
10        init_data_internal::TelegramInitDataInternal, theme_params::TelegramThemeParams,
11        user::TelegramUser
12    }
13};
14
15/// Initializes Telegram WebApp SDK by extracting and validating context.
16///
17/// - Parses `initData` (urlencoded) with embedded JSON.
18/// - Parses `themeParams` (object).
19/// - Initializes global context.
20///
21/// # Errors
22/// Returns `Err(JsValue)` on failure to access JS globals, parse, or init
23/// context.
24pub fn init_sdk() -> Result<(), JsValue> {
25    let win = window().ok_or_else(|| JsValue::from_str("window is not available"))?;
26    let telegram = Reflect::get(&win, &"Telegram".into())?;
27    let webapp = Reflect::get(&telegram, &"WebApp".into())?;
28
29    // === 1. Parse initData string ===
30    let init_data_str = Reflect::get(&webapp, &"initData".into())?
31        .as_string()
32        .ok_or_else(|| JsValue::from_str("Telegram.WebApp.initData is not a string"))?;
33
34    let raw: TelegramInitDataInternal = serde_urlencoded::from_str(&init_data_str)
35        .map_err(|e| JsValue::from_str(&format!("Failed to parse initData: {e}")))?;
36
37    // === 2. Parse embedded JSON fields ===
38    let user: Option<TelegramUser> = raw
39        .user
40        .as_deref()
41        .map(serde_json::from_str)
42        .transpose()
43        .map_err(|e| JsValue::from_str(&format!("Failed to parse user: {e}")))?;
44
45    let receiver: Option<TelegramUser> = raw
46        .receiver
47        .as_deref()
48        .map(serde_json::from_str)
49        .transpose()
50        .map_err(|e| JsValue::from_str(&format!("Failed to parse receiver: {e}")))?;
51
52    let chat: Option<TelegramChat> = raw
53        .chat
54        .as_deref()
55        .map(serde_json::from_str)
56        .transpose()
57        .map_err(|e| JsValue::from_str(&format!("Failed to parse chat: {e}")))?;
58
59    // === 3. Construct final typed initData ===
60    let init_data = TelegramInitData {
61        query_id: raw.query_id,
62        user,
63        receiver,
64        chat,
65        chat_type: raw.chat_type,
66        chat_instance: raw.chat_instance,
67        start_param: raw.start_param,
68        can_send_after: raw.can_send_after,
69        auth_date: raw.auth_date,
70        hash: raw.hash,
71        signature: raw.signature
72    };
73
74    // === 4. Parse themeParams ===
75    let theme_val = Reflect::get(&webapp, &"themeParams".into())?;
76    let theme_params: TelegramThemeParams = from_value(theme_val)?;
77
78    // theme_params.clone().apply_to_root();
79
80    // === 5. Init global context ===
81    TelegramContext::init(init_data, theme_params)?;
82
83    Ok(())
84}