forked from Lonami/grammers
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dialogs.rs
108 lines (93 loc) · 3.58 KB
/
dialogs.rs
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
//! Example to print the ID and title of all the dialogs.
//!
//! The `TG_ID` and `TG_HASH` environment variables must be set (learn how to do it for
//! [Windows](https://ss64.com/nt/set.html) or [Linux](https://ss64.com/bash/export.html))
//! to Telegram's API ID and API hash respectively.
//!
//! Then, run it as:
//!
//! ```sh
//! cargo run --example dialogs
//! ```
use grammers_client::{Client, Config, SignInError};
use grammers_session::Session;
use log;
use simple_logger::SimpleLogger;
use std::env;
use std::io::{self, BufRead as _, Write as _};
use tokio::{runtime, task};
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
fn prompt(message: &str) -> Result<String> {
let stdout = io::stdout();
let mut stdout = stdout.lock();
stdout.write_all(message.as_bytes())?;
stdout.flush()?;
let stdin = io::stdin();
let mut stdin = stdin.lock();
let mut line = String::new();
stdin.read_line(&mut line)?;
Ok(line)
}
async fn async_main() -> Result<()> {
SimpleLogger::new()
.with_level(log::LevelFilter::Debug)
.init()
.unwrap();
let api_id = env!("TG_ID").parse().expect("TG_ID invalid");
let api_hash = env!("TG_HASH").to_string();
println!("Connecting to Telegram...");
let mut client = Client::connect(Config {
session: Session::load_or_create("dialogs.session")?,
api_id,
api_hash: api_hash.clone(),
params: Default::default(),
})
.await?;
println!("Connected!");
if !client.is_authorized().await? {
println!("Signing in...");
let phone = prompt("Enter your phone number (international format): ")?;
let token = client.request_login_code(&phone, api_id, &api_hash).await?;
let code = prompt("Enter the code you received: ")?;
let signed_in = client.sign_in(&token, &code).await;
match signed_in {
Err(SignInError::PasswordRequired(password_token)) => {
// Note: this `prompt` method will echo the password in the console.
// Real code might want to use a better way to handle this.
let hint = password_token.hint().unwrap();
let prompt_message = format!("Enter the password (hint {}): ", &hint);
let password = prompt(prompt_message.as_str())?;
client
.check_password(password_token, password.trim())
.await?;
}
Ok(_) => (),
Err(e) => panic!(e),
};
println!("Signed in!");
}
// Obtain a `ClientHandle` to perform remote calls while `Client` drives the connection.
//
// This handle can be `clone()`'d around and freely moved into other tasks, so you can invoke
// methods concurrently if you need to. While you do this, the single owned `client` is the
// one that communicates with the network.
//
// The design's annoying to use for trivial sequential tasks, but is otherwise scalable.
let mut client_handle = client.handle();
let network_handle = task::spawn(async move { client.run_until_disconnected().await });
let mut dialogs = client_handle.iter_dialogs();
println!("Showing up to {} dialogs:", dialogs.total().await?);
while let Some(dialog) = dialogs.next().await? {
println!("- {: >10} {}", dialog.id(), dialog.title());
}
client_handle.disconnect().await;
network_handle.await??;
Ok(())
}
fn main() -> Result<()> {
runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(async_main())
}