Some checks failed
ci/woodpecker/pr/check Pipeline was successful
CI / Check (pull_request) Has been cancelled
CI / Format (pull_request) Has been cancelled
CI / Clippy (pull_request) Has been cancelled
CI / Build (macos-latest) (pull_request) Has been cancelled
CI / Build (ubuntu-latest) (pull_request) Has been cancelled
CI / Build (windows-latest) (pull_request) Has been cancelled
- Add #[allow(unused_imports)] on pub re-exports used only by lib/tests - Add #[allow(dead_code)] on public API items unused in binary target - Fix collapsible_if, redundant_closure, unnecessary_map_or in main.rs - Prefix unused test variables with underscore Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
216 lines
8.2 KiB
Rust
216 lines
8.2 KiB
Rust
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))
|
||
}
|
||
}
|