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
use std::{fmt::Debug, sync::Arc};

use async_lock::RwLock;
use log::{error, info};
use serde::Deserialize;

use crate::api::{
    context::BotXApiContext,
    result::{BotXApiError, BotXApiResult},
    v2::token::api::token,
};

use std::future::Future;

pub async fn retry_with_auth<Fut, TResponse, TError, TRequest: Fn() -> Fut>(
    context: &Arc<RwLock<BotXApiContext>>,
    request: TRequest,
) -> Result<TResponse, BotXApiError<TError>>
where
    // for<'a> TResponse: Deserialize<'a> + Debug,
    // for<'a> TError: Deserialize<'a> + Debug,
    Fut: Future<Output = BotXApiResult<TResponse, TError>>,
{
    let response = (request)().await;

    let Err(err) = response else {
        return response
    };

    if !err.is_unauthorized() {
        return Result::<TResponse, BotXApiError<TError>>::Err(err);
    }

    info!("Действие токена истекло, презапрашиваем");

    let mut context_write_lock = context.write().await;
    let token_response = token(&mut *context_write_lock).await;

    let Ok(token_result) = token_response else {
        error!("Не удалось повторить запрос с переавторизацией");
        return Result::<TResponse, BotXApiError<TError>>::Err(err);
    };

    context_write_lock.auth_token = Some(token_result.token);

    (request)().await
}