Split core and TUI crates

This commit is contained in:
Mikhail Kilin
2026-05-20 00:31:18 +03:00
parent 91a8700b8e
commit eefac431e5
238 changed files with 624 additions and 191 deletions

View File

@@ -0,0 +1,215 @@
use tdlib_rs::enums::{AuthorizationState, Update};
use tdlib_rs::functions;
/// Состояние процесса авторизации в Telegram.
///
/// Отслеживает текущий этап аутентификации пользователя,
/// от инициализации TDLib до полной авторизации.
#[allow(dead_code)]
#[derive(Debug, Clone, PartialEq)]
pub enum AuthState {
/// Ожидание параметров TDLib (начальное состояние).
WaitTdlibParameters,
/// Ожидание ввода номера телефона.
WaitPhoneNumber,
/// Ожидание ввода кода подтверждения из SMS/Telegram.
WaitCode,
/// Ожидание ввода пароля двухфакторной аутентификации (2FA).
WaitPassword,
/// Авторизация завершена, клиент готов к работе.
Ready,
/// Соединение закрыто.
Closed,
/// Произошла ошибка авторизации.
Error(String),
}
/// Менеджер авторизации TDLib.
///
/// Управляет процессом авторизации пользователя в Telegram,
/// отслеживает текущее состояние и предоставляет методы
/// для отправки учетных данных (номер телефона, код, пароль).
///
/// # Процесс авторизации
///
/// 1. `WaitTdlibParameters` → автоматически
/// 2. `WaitPhoneNumber` → [`send_phone_number()`](Self::send_phone_number)
/// 3. `WaitCode` → [`send_code()`](Self::send_code)
/// 4. `WaitPassword` (опционально) → [`send_password()`](Self::send_password)
/// 5. `Ready` → авторизация завершена
///
/// # Examples
///
/// ```ignore
/// let mut auth_manager = AuthManager::new(client_id);
///
/// // Отправляем номер телефона
/// auth_manager.send_phone_number("+1234567890".to_string()).await?;
///
/// // После получения кода из SMS
/// auth_manager.send_code("12345".to_string()).await?;
///
/// // Если включена 2FA
/// if auth_manager.state == AuthState::WaitPassword {
/// auth_manager.send_password("my_password".to_string()).await?;
/// }
///
/// // Проверяем авторизацию
/// if auth_manager.is_authenticated() {
/// println!("Successfully authenticated!");
/// }
/// ```
pub struct AuthManager {
/// Текущее состояние авторизации.
pub state: AuthState,
/// ID клиента TDLib для API вызовов.
client_id: i32,
}
#[allow(dead_code)]
impl AuthManager {
/// Создает новый менеджер авторизации.
///
/// # Arguments
///
/// * `client_id` - ID клиента TDLib для API вызовов
///
/// # Returns
///
/// Новый экземпляр `AuthManager` в состоянии `WaitTdlibParameters`.
pub fn new(client_id: i32) -> Self {
Self { state: AuthState::WaitTdlibParameters, client_id }
}
/// Проверяет, завершена ли авторизация.
///
/// # Returns
///
/// `true` если состояние равно `AuthState::Ready`, иначе `false`.
///
/// # Examples
///
/// ```ignore
/// if auth_manager.is_authenticated() {
/// println!("User is authenticated");
/// }
/// ```
pub fn is_authenticated(&self) -> bool {
self.state == AuthState::Ready
}
/// Обрабатывает обновление состояния авторизации от TDLib.
///
/// Автоматически обновляет внутреннее состояние [`AuthState`] на основе
/// полученного update от TDLib.
///
/// # Arguments
///
/// * `update` - Обновление от TDLib (проверяется на `Update::AuthorizationState`)
///
/// # Note
///
/// Этот метод должен вызываться для каждого update от TDLib,
/// чтобы состояние авторизации оставалось актуальным.
pub fn handle_auth_update(&mut self, update: &Update) {
if let Update::AuthorizationState(auth_update) = update {
self.state = match &auth_update.authorization_state {
AuthorizationState::WaitTdlibParameters => AuthState::WaitTdlibParameters,
AuthorizationState::WaitPhoneNumber => AuthState::WaitPhoneNumber,
AuthorizationState::WaitCode(_) => AuthState::WaitCode,
AuthorizationState::WaitPassword(_) => AuthState::WaitPassword,
AuthorizationState::Ready => AuthState::Ready,
AuthorizationState::Closed => AuthState::Closed,
_ => return,
};
}
}
/// Отправляет номер телефона для авторизации.
///
/// Используется на этапе [`AuthState::WaitPhoneNumber`].
/// После успешной отправки состояние изменится на `WaitCode`.
///
/// # Arguments
///
/// * `phone` - Номер телефона в международном формате (например, "+1234567890")
///
/// # Returns
///
/// * `Ok(())` - Номер телефона принят, ожидайте SMS с кодом
/// * `Err(String)` - Ошибка (неверный формат, проблемы с сетью и т.д.)
///
/// # Examples
///
/// ```ignore
/// auth_manager.send_phone_number("+1234567890".to_string()).await?;
/// ```
pub async fn send_phone_number(&self, phone: String) -> Result<(), String> {
functions::set_authentication_phone_number(phone, None, self.client_id)
.await
.map(|_| ())
.map_err(|e| format!("Ошибка отправки номера: {:?}", e))
}
/// Отправляет код подтверждения из SMS или Telegram.
///
/// Используется на этапе [`AuthState::WaitCode`].
/// После успешной проверки состояние изменится на `Ready` или `WaitPassword`
/// (если включена двухфакторная аутентификация).
///
/// # Arguments
///
/// * `code` - Код подтверждения (обычно 5 цифр)
///
/// # Returns
///
/// * `Ok(())` - Код верный
/// * `Err(String)` - Неверный код или истек срок действия
///
/// # Examples
///
/// ```ignore
/// auth_manager.send_code("12345".to_string()).await?;
/// ```
pub async fn send_code(&self, code: String) -> Result<(), String> {
functions::check_authentication_code(code, self.client_id)
.await
.map(|_| ())
.map_err(|e| format!("Ошибка проверки кода: {:?}", e))
}
/// Отправляет пароль двухфакторной аутентификации (2FA).
///
/// Используется на этапе [`AuthState::WaitPassword`] (только если 2FA включена).
/// После успешной проверки состояние изменится на `Ready`.
///
/// # Arguments
///
/// * `password` - Пароль двухфакторной аутентификации
///
/// # Returns
///
/// * `Ok(())` - Пароль верный, авторизация завершена
/// * `Err(String)` - Неверный пароль
///
/// # Examples
///
/// ```ignore
/// if auth_manager.state == AuthState::WaitPassword {
/// auth_manager.send_password("my_2fa_password".to_string()).await?;
/// }
/// ```
pub async fn send_password(&self, password: String) -> Result<(), String> {
functions::check_authentication_password(password, self.client_id)
.await
.map(|_| ())
.map_err(|e| format!("Ошибка проверки пароля: {:?}", e))
}
}