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
use crate::{config::Config, credential::Credential, RequestResult};
use reqwest::{header, Client, Method, Request, RequestBuilder};
use url::Url;

#[derive(Debug, Clone)]
pub struct ApiClient<'a> {
    credential: Credential<'a>,
    inner: TalkHttpClient<'a>,
}

impl<'a> ApiClient<'a> {
    pub const fn new(credential: Credential<'a>, inner: TalkHttpClient<'a>) -> Self {
        Self { credential, inner }
    }

    pub fn request(self, method: Method, end_point: &str) -> RequestResult<RequestBuilder> {
        Ok(self.inner.request(method, end_point)?.header(
            header::AUTHORIZATION,
            format!(
                "{}-{}",
                self.credential.access_token, self.credential.device_uuid
            ),
        ))
    }
}

#[derive(Debug, Clone)]
pub struct TalkHttpClient<'a> {
    pub config: Config<'a>,
    url: Url,
    client: Client,
}

impl<'a> TalkHttpClient<'a> {
    pub const fn new(config: Config<'a>, url: Url, client: Client) -> Self {
        Self {
            config,
            url,
            client,
        }
    }

    pub fn request(self, method: Method, end_point: &str) -> RequestResult<RequestBuilder> {
        let user_agent = self.config.get_user_agent();

        let url = self
            .url
            .join(&format!("{}/{}", self.config.agent.agent(), end_point))?;

        let host = url.host_str().map(ToString::to_string);

        let mut builder = RequestBuilder::from_parts(self.client, Request::new(method, url))
            .header(header::USER_AGENT, user_agent)
            .header(
                "A",
                format!(
                    "{}/{}/{}",
                    self.config.agent.agent(),
                    self.config.version,
                    self.config.language
                ),
            )
            .header(header::ACCEPT, "*/*")
            .header(header::ACCEPT_LANGUAGE, self.config.language);

        if let Some(host) = host {
            builder = builder.header(header::HOST, host);
        }

        Ok(builder)
    }
}