1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
// cargo run -p tdlib-rs --example get_me --features default
// cargo run -p tdlib-rs --example get_me --features download-tdlib
// cargo run -p tdlib-rs --example get_me --features pkg-config
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};
use tdlib_rs::{
enums::{self, 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>,
) -> Receiver<AuthorizationState> {
while let Some(state) = auth_rx.recv().await {
match state {
AuthorizationState::WaitTdlibParameters => {
let response = functions::set_tdlib_parameters(
false,
"get_me_db".into(),
String::new(),
String::new(),
false,
false,
false,
false,
env!("API_ID").parse().unwrap(),
env!("API_HASH").into(),
"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::WaitOtherDeviceConfirmation(x) => {
println!(
"Please confirm this login link on another device: {}",
x.link
);
}
AuthorizationState::WaitEmailAddress(_x) => {
let email_address = ask_user("Please enter email address: ");
let response =
functions::set_authentication_email_address(email_address, client_id).await;
match response {
Ok(_) => break,
Err(e) => println!("{}", e.message),
}
}
AuthorizationState::WaitEmailCode(_x) => {
let code = ask_user("Please enter email authentication code: ");
let response = functions::check_authentication_email_code(
enums::EmailAddressAuthentication::Code(
tdlib_rs::types::EmailAddressAuthenticationCode { code },
),
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::WaitRegistration(_x) => {
// x useless but contains the TOS if we want to show it
let first_name = ask_user("Please enter your first name: ");
let last_name = ask_user("Please enter your last name: ");
functions::register_user(first_name, last_name, false, client_id)
.await
.unwrap();
}
AuthorizationState::WaitPassword(_x) => {
let password = ask_user("Please enter password: ");
functions::check_authentication_password(password, client_id)
.await
.unwrap();
}
AuthorizationState::Ready => {
break;
}
AuthorizationState::Closed => {
// Set the flag to false to stop receiving updates from the
// spawned task
run_flag.store(false, Ordering::Release);
break;
}
_ => (),
}
}
auth_rx
}
#[tokio::main]
async fn main() {
// Create the client object
let client_id = tdlib_rs::create_client();
// Create a mpsc channel for handling AuthorizationState updates separately
// from the task
let (auth_tx, auth_rx) = mpsc::channel(5);
// Create a flag to make it possible to stop receiving updates
let run_flag = Arc::new(AtomicBool::new(true));
let run_flag_clone = run_flag.clone();
// Spawn a task to receive updates/responses
let handle = tokio::spawn(async move {
while run_flag_clone.load(Ordering::Acquire) {
if let Some((update, _client_id)) = tdlib_rs::receive() {
handle_update(update, &auth_tx).await;
}
}
});
// Set a fairly low verbosity level. We mainly do this because tdlib
// requires to perform a random request with the client to start receiving
// updates for it.
functions::set_log_verbosity_level(2, client_id)
.await
.unwrap();
// Handle the authorization state to authenticate the client
let auth_rx = handle_authorization_state(client_id, auth_rx, run_flag.clone()).await;
// Run the get_me() method to get user information
let User::User(me) = functions::get_me(client_id).await.unwrap();
println!("Hi, I'm {}", me.first_name);
// Tell the client to close
functions::close(client_id).await.unwrap();
// Handle the authorization state to wait for the "Closed" state
handle_authorization_state(client_id, auth_rx, run_flag.clone()).await;
// Wait for the previously spawned task to end the execution
handle.await.unwrap();
}
|