use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};
use tdlib_rs::{
enums::{AuthorizationState, Update, User},
functions,
};
use tokio::sync::mpsc::{self, Receiver, Sender};
fn ask_user(string: &str) -> String {
println!("{}", string);
let mut input = String::new();
std::io::stdin().read_line(&mut input).unwrap();
input.trim().to_string()
}
async fn handle_update(update: Update, auth_tx: &Sender<AuthorizationState>) {
if let Update::AuthorizationState(update) = update {
auth_tx.send(update.authorization_state).await.unwrap();
}
}
async fn handle_authorization_state(
client_id: i32,
mut auth_rx: Receiver<AuthorizationState>,
run_flag: Arc<AtomicBool>,
) -> Option<Receiver<AuthorizationState>> {
let api_id: i32 = {
if let Ok(api_id) = std::env::var("API_ID") {
api_id.parse().unwrap()
} else {
tracing::error!("API_ID not found in environment");
"94575".parse().unwrap() }
};
let api_hash: String = {
if let Ok(api_hash) = std::env::var("API_HASH") {
api_hash
} else {
"a3406de8d171bb422bb6ddf3bbd800e2".into() }
};
while let Some(state) = auth_rx.recv().await {
match state {
AuthorizationState::WaitTdlibParameters => {
let response = functions::set_tdlib_parameters(
false,
".data/example".into(),
String::new(),
String::new(),
false,
false,
false,
false,
api_id,
api_hash.clone(),
"en".into(),
"Desktop".into(),
String::new(),
env!("CARGO_PKG_VERSION").into(),
client_id,
)
.await;
if let Err(error) = response {
println!("{}", error.message);
}
}
AuthorizationState::WaitPhoneNumber => loop {
let input = ask_user("Enter your phone number (include the country calling code):");
let response =
functions::set_authentication_phone_number(input, None, client_id).await;
match response {
Ok(_) => break,
Err(e) => println!("{}", e.message),
}
},
AuthorizationState::WaitCode(_) => loop {
let input = ask_user("Enter the verification code:");
let response = functions::check_authentication_code(input, client_id).await;
match response {
Ok(_) => break,
Err(e) => println!("{}", e.message),
}
},
AuthorizationState::Ready => {
break;
}
AuthorizationState::Closed => {
run_flag.store(false, Ordering::Release);
return None;
}
_ => (),
}
}
Some(auth_rx)
}
#[tokio::main]
async fn main() {
let client_id = tdlib_rs::create_client();
let (auth_tx, auth_rx) = mpsc::channel(5);
let run_flag = Arc::new(AtomicBool::new(true));
let run_flag_clone = run_flag.clone();
let handle = tokio::spawn(async move {
loop {
if !run_flag_clone.load(Ordering::Acquire) {
break;
}
if let Some((update, _client_id)) = tdlib_rs::receive() {
handle_update(update, &auth_tx).await;
}
}
});
functions::set_log_verbosity_level(2, client_id)
.await
.unwrap();
let auth_rx = handle_authorization_state(client_id, auth_rx, run_flag.clone())
.await
.unwrap();
let User::User(me) = functions::get_me(client_id).await.unwrap();
println!("Hi, I'm {}", me.first_name);
functions::close(client_id).await.unwrap();
match handle_authorization_state(client_id, auth_rx, run_flag.clone()).await {
None => std::process::exit(0),
Some(_) => (),
}
println!("BEFORE");
match handle.await {
Ok(_) => (),
Err(e) => println!("Error: {:?}", e),
}
println!("AFTER");
}