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

use reqwest::Client;

#[cfg(feature = "anthill-di")]
use anthill_di::{Constructor, DependencyContext, types::BuildDependencyResult};

use crate::api::utils::url::ApiEndpoints;

pub struct BotXApiContext {
    pub cts_url: String,
    pub bot_id: String,
    pub secret_key: String,
    pub client: Client,
    pub api: ApiEndpoints,
    pub auth_token: Option<String>,
}

/// При интеграции с anthill-di позволяет переопределить настройки бота (по умолчанию берется информация из переменных среды) <br/>
/// Чтобы переопределить, зарегистрируйте фабрику на основе замыкания с настройкой необходимой конфигурации
/// ```rs
/// ioc.register_closure(|| Ok(BotXApiContextConfiguration { cts_url: "http:xxxx.ru", ... }), LifeTime::Transient).await.unwrap();
/// ```

pub struct BotXApiContextConfiguration {
    pub cts_url: String,
    pub bot_id: String,
    pub secret_key: String,
}

impl BotXApiContextConfiguration {
    pub const DEFAULT_CTS_URL_ENV: &str = "BOTX_API_CTS_URL";
    pub const DEFAULT_BOT_ID_ENV: &str = "BOTX_API_BOT_ID";
    pub const DEFAULT_BOT_SECRET_KEY_ENV: &str = "BOTX_API_BOT_SECRET_KEY";
}

impl Default for BotXApiContextConfiguration {
    fn default() -> Self {
        let cts_url = env::var(Self::DEFAULT_CTS_URL_ENV)
            .expect(&*format!("Env {} not found", Self::DEFAULT_CTS_URL_ENV));

        let bot_id = env::var(Self::DEFAULT_BOT_ID_ENV)
            .expect(&*format!("Env {} not found", Self::DEFAULT_BOT_ID_ENV));

        let secret_key = env::var(Self::DEFAULT_BOT_SECRET_KEY_ENV)
            .expect(&*format!("Env {} not found", Self::DEFAULT_BOT_SECRET_KEY_ENV));

        Self { cts_url, bot_id, secret_key }
    }
}

#[cfg(feature = "anthill-di")]
#[async_trait_with_sync::async_trait(Sync)]
impl Constructor for BotXApiContext {
    async fn ctor(ctx: DependencyContext) -> BuildDependencyResult<Self> {
        let configuration = ctx.resolve::<Arc<BotXApiContextConfiguration>>().await.unwrap_or(Arc::new(BotXApiContextConfiguration::default()));
        
        Ok(Self {
            cts_url: configuration.cts_url.clone().into(),
            bot_id: configuration.bot_id.clone().into(),
            secret_key: configuration.secret_key.clone().into(),
            client: ctx.resolve().await.unwrap_or_default(),
            api: ctx.resolve().await.unwrap_or_default(),
            auth_token: None,
        })
    }
}

impl BotXApiContext {
    

    pub fn new(cts_url: impl Into<String>, bot_id: impl Into<String>, secret_key: impl Into<String>) -> Self {
        Self::from_client(cts_url, bot_id, secret_key, Default::default())
    }

    pub fn from_client(cts_url: impl Into<String>, bot_id: impl Into<String>, secret_key: impl Into<String>, client: Client) -> Self {
        Self {
            cts_url: cts_url.into(),
            bot_id: bot_id.into(),
            secret_key: secret_key.into(),
            client,
            api: ApiEndpoints::new(),
            auth_token: None,
        }
    }

    pub fn from_env_with_default_client() -> Self {
        Self::from_env(Default::default())
    }

    pub fn from_env(client: Client) -> Self {
        let BotXApiContextConfiguration{ cts_url, bot_id, secret_key } = BotXApiContextConfiguration::default();

        Self {
            cts_url: cts_url.into(),
            bot_id: bot_id.into(),
            secret_key: secret_key.into(),
            client,
            api: ApiEndpoints::new(),
            auth_token: None,
        }
    }

    pub fn cts_url(&self) -> &str {
        self.cts_url.as_ref()
    }

    pub fn bot_id(&self) -> &str {
        self.bot_id.as_ref()
    }

    pub fn secret_key(&self) -> &str {
        self.secret_key.as_ref()
    }
}