1use std::fmt::Debug;
2use std::sync::Arc;
3
4use async_trait::async_trait;
5use dyn_clone::DynClone;
6use tokio::sync::Mutex;
7
8use crate::types::{
9 AuthorizationStateWaitCode, AuthorizationStateWaitEncryptionKey,
10 AuthorizationStateWaitOtherDeviceConfirmation, AuthorizationStateWaitPassword,
11 AuthorizationStateWaitPhoneNumber, AuthorizationStateWaitRegistration,
12};
13
14use crate::utils;
15
16#[derive(Debug, Clone)]
18pub enum ClientIdentifier {
19 PhoneNumber(String),
20 BotToken(String),
21}
22
23#[async_trait]
26pub trait ClientAuthStateHandler: DynClone + Send + Sync + Debug {
27 async fn handle_other_device_confirmation(
29 &self,
30 wait_device_confirmation: &AuthorizationStateWaitOtherDeviceConfirmation,
31 ) {
32 println!(
33 "other device confirmation link: {}",
34 wait_device_confirmation.link()
35 );
36 }
37 async fn handle_wait_code(&self, wait_code: &AuthorizationStateWaitCode) -> String;
39 async fn handle_encryption_key(
41 &self,
42 wait_encryption_key: &AuthorizationStateWaitEncryptionKey,
43 ) -> String;
44 async fn handle_wait_password(&self, wait_password: &AuthorizationStateWaitPassword) -> String;
46 async fn handle_wait_client_identifier(
48 &self,
49 wait_phone_number: &AuthorizationStateWaitPhoneNumber,
50 ) -> ClientIdentifier;
51 async fn handle_wait_registration(
53 &self,
54 wait_registration: &AuthorizationStateWaitRegistration,
55 ) -> (String, String);
56}
57
58dyn_clone::clone_trait_object!(ClientAuthStateHandler);
59
60#[async_trait]
63pub trait AuthStateHandler {
64 async fn handle_other_device_confirmation(
66 &self,
67 _client: Box<dyn ClientAuthStateHandler>,
68 wait_device_confirmation: &AuthorizationStateWaitOtherDeviceConfirmation,
69 ) {
70 println!(
71 "other device confirmation link: {}",
72 wait_device_confirmation.link()
73 );
74 }
75 async fn handle_wait_code(
77 &self,
78 client: Box<dyn ClientAuthStateHandler>,
79 wait_code: &AuthorizationStateWaitCode,
80 ) -> String;
81 async fn handle_encryption_key(
83 &self,
84 client: Box<dyn ClientAuthStateHandler>,
85 wait_encryption_key: &AuthorizationStateWaitEncryptionKey,
86 ) -> String;
87 async fn handle_wait_password(
89 &self,
90 client: Box<dyn ClientAuthStateHandler>,
91 wait_password: &AuthorizationStateWaitPassword,
92 ) -> String;
93 async fn handle_wait_client_identifier(
95 &self,
96 client: Box<dyn ClientAuthStateHandler>,
97 wait_phone_number: &AuthorizationStateWaitPhoneNumber,
98 ) -> ClientIdentifier;
99 async fn handle_wait_registration(
101 &self,
102 client: Box<dyn ClientAuthStateHandler>,
103 wait_registration: &AuthorizationStateWaitRegistration,
104 ) -> (String, String);
105}
106
107#[derive(Debug, Clone)]
110#[deprecated(
111 since = "0.4.3",
112 note = "use ClientAuthStateHandler trait implementations bound to particular client with AuthStateHandlerProxy bound to worker"
113)]
114pub struct ConsoleAuthStateHandler;
115
116impl Default for ConsoleAuthStateHandler {
117 fn default() -> Self {
118 Self::new()
119 }
120}
121
122impl ConsoleAuthStateHandler {
123 pub fn new() -> Self {
124 Self
125 }
126}
127
128#[async_trait]
129impl AuthStateHandler for ConsoleAuthStateHandler {
130 async fn handle_wait_code(
131 &self,
132 _client: Box<dyn ClientAuthStateHandler>,
133 _wait_code: &AuthorizationStateWaitCode,
134 ) -> String {
135 println!("waiting for auth code");
136 utils::wait_input_sync()
137 }
138
139 async fn handle_encryption_key(
140 &self,
141 _client: Box<dyn ClientAuthStateHandler>,
142 _wait_encryption_key: &AuthorizationStateWaitEncryptionKey,
143 ) -> String {
144 println!("waiting for encryption key");
145 utils::wait_input_sync()
146 }
147
148 async fn handle_wait_password(
149 &self,
150 _client: Box<dyn ClientAuthStateHandler>,
151 _wait_password: &AuthorizationStateWaitPassword,
152 ) -> String {
153 println!("waiting for password");
154 utils::wait_input_sync()
155 }
156
157 async fn handle_wait_client_identifier(
158 &self,
159 _client: Box<dyn ClientAuthStateHandler>,
160 _: &AuthorizationStateWaitPhoneNumber,
161 ) -> ClientIdentifier {
162 loop {
163 println!("choose one of phone number (p) or bot token (b)");
164 let inp = utils::wait_input_sync();
165 match inp.to_lowercase().trim() {
166 "b" => {
167 println!("enter bot token");
168 return ClientIdentifier::BotToken(utils::wait_input_sync());
169 }
170 "p" => {
171 println!("enter phone number");
172 return ClientIdentifier::PhoneNumber(utils::wait_input_sync());
173 }
174 _ => {
175 continue;
177 }
178 }
179 }
180 }
181 async fn handle_wait_registration(
182 &self,
183 _client: Box<dyn ClientAuthStateHandler>,
184 _wait_registration: &AuthorizationStateWaitRegistration,
185 ) -> (String, String) {
186 loop {
187 println!("waiting for first_name and second_name separated by comma");
188 let inp: String = utils::wait_input_sync();
189 if let Some((f, l)) = utils::split_string(inp, ',') {
190 return (f, l);
191 }
192 }
193 }
194}
195
196#[derive(Debug, Clone)]
198#[deprecated(
199 since = "0.4.3",
200 note = "use ClientAuthStateHandler trait implementations bound to particular client with AuthStateHandlerProxy bound to worker"
201)]
202pub struct SignalAuthStateHandler {
203 rec: Arc<Mutex<tokio::sync::mpsc::Receiver<String>>>,
204}
205
206impl SignalAuthStateHandler {
207 pub fn new(receiver: tokio::sync::mpsc::Receiver<String>) -> Self {
208 Self {
209 rec: Arc::new(Mutex::new(receiver)),
210 }
211 }
212
213 async fn wait_signal(&self) -> String {
214 let mut guard = self.rec.lock().await;
215 guard.recv().await.expect("no signals received")
216 }
217}
218
219#[async_trait]
220impl AuthStateHandler for SignalAuthStateHandler {
221 async fn handle_wait_code(
222 &self,
223 _client: Box<dyn ClientAuthStateHandler>,
224 _: &AuthorizationStateWaitCode,
225 ) -> String {
226 log::info!("waiting for auth code");
227 self.wait_signal().await
228 }
229
230 async fn handle_encryption_key(
231 &self,
232 _client: Box<dyn ClientAuthStateHandler>,
233 _: &AuthorizationStateWaitEncryptionKey,
234 ) -> String {
235 log::info!("waiting for encryption key");
236 let f = self.wait_signal().await;
237 log::info!("get encryption key");
238 f
239 }
240
241 async fn handle_wait_password(
242 &self,
243 _client: Box<dyn ClientAuthStateHandler>,
244 _: &AuthorizationStateWaitPassword,
245 ) -> String {
246 log::info!("waiting for password");
247 self.wait_signal().await
248 }
249
250 async fn handle_wait_client_identifier(
251 &self,
252 _client: Box<dyn ClientAuthStateHandler>,
253 _: &AuthorizationStateWaitPhoneNumber,
254 ) -> ClientIdentifier {
255 loop {
256 log::info!("choose one of phone number (p) or bot token (b)");
257 let inp = self.wait_signal().await;
258 match inp.to_lowercase().trim() {
259 "b" => {
260 log::info!("enter bot token");
261 return ClientIdentifier::BotToken(self.wait_signal().await);
262 }
263 "p" => {
264 log::info!("enter phone number");
265 return ClientIdentifier::PhoneNumber(self.wait_signal().await);
266 }
267 _ => {
268 continue;
270 }
271 }
272 }
273 }
274
275 async fn handle_wait_registration(
276 &self,
277 _client: Box<dyn ClientAuthStateHandler>,
278 _: &AuthorizationStateWaitRegistration,
279 ) -> (String, String) {
280 loop {
281 log::info!("waiting for first name and last name separated by comma");
282 let inp = self.wait_signal().await;
283 if let Some((f, l)) = utils::split_string(inp, ',') {
284 return (f, l);
285 }
286 }
287 }
288}
289
290#[derive(Debug, Clone)]
292pub struct AuthStateHandlerProxy(Option<String>);
293
294impl AuthStateHandlerProxy {
295 pub fn new() -> Self {
296 Self(None)
297 }
298
299 pub fn new_with_encryption_key(key: String) -> Self {
300 Self(Some(key))
301 }
302}
303
304impl Default for AuthStateHandlerProxy {
305 fn default() -> Self {
306 Self::new()
307 }
308}
309
310#[async_trait]
311impl AuthStateHandler for AuthStateHandlerProxy {
312 async fn handle_other_device_confirmation(
313 &self,
314 client: Box<dyn ClientAuthStateHandler>,
315 wait_device_confirmation: &AuthorizationStateWaitOtherDeviceConfirmation,
316 ) {
317 client
318 .handle_other_device_confirmation(wait_device_confirmation)
319 .await
320 }
321
322 async fn handle_wait_code(
323 &self,
324 client: Box<dyn ClientAuthStateHandler>,
325 wait_code: &AuthorizationStateWaitCode,
326 ) -> String {
327 client.handle_wait_code(wait_code).await
328 }
329
330 async fn handle_encryption_key(
331 &self,
332 client: Box<dyn ClientAuthStateHandler>,
333 wait_encryption_key: &AuthorizationStateWaitEncryptionKey,
334 ) -> String {
335 match &self.0 {
336 None => {
337 log::info!("wait for client's encryption key");
338 client.handle_encryption_key(wait_encryption_key).await
339 }
340 Some(key) => key.clone(),
341 }
342 }
343
344 async fn handle_wait_password(
345 &self,
346 client: Box<dyn ClientAuthStateHandler>,
347 wait_password: &AuthorizationStateWaitPassword,
348 ) -> String {
349 client.handle_wait_password(wait_password).await
350 }
351
352 async fn handle_wait_client_identifier(
353 &self,
354 client: Box<dyn ClientAuthStateHandler>,
355 wait_phone_number: &AuthorizationStateWaitPhoneNumber,
356 ) -> ClientIdentifier {
357 client
358 .handle_wait_client_identifier(wait_phone_number)
359 .await
360 }
361
362 async fn handle_wait_registration(
363 &self,
364 client: Box<dyn ClientAuthStateHandler>,
365 wait_registration: &AuthorizationStateWaitRegistration,
366 ) -> (String, String) {
367 client.handle_wait_registration(wait_registration).await
368 }
369}