Skip to main content

bpi_rs/clientinfo/
client.rs

1use crate::request::BilibiliRequest;
2use crate::{BpiClient, BpiResult};
3
4use super::{ClientInfoIpParams, IpInfo};
5
6const IP_ENDPOINT: &str = "https://api.live.bilibili.com/ip_service/v1/ip_service/get_ip_addr";
7
8/// Client information API client.
9#[derive(Clone, Copy)]
10pub struct ClientInfoClient<'a> {
11    pub(crate) client: &'a BpiClient,
12}
13
14impl<'a> ClientInfoClient<'a> {
15    pub(crate) fn new(client: &'a BpiClient) -> Self {
16        Self { client }
17    }
18
19    #[cfg(test)]
20    pub(crate) fn ip_endpoint(&self) -> &'static str {
21        IP_ENDPOINT
22    }
23
24    /// Queries IP geolocation information.
25    pub async fn ip(&self, params: ClientInfoIpParams) -> BpiResult<IpInfo> {
26        self.client
27            .get(IP_ENDPOINT)
28            .query(&params.query_pairs())
29            .send_bpi_payload("clientinfo.ip")
30            .await
31    }
32}
33
34#[cfg(test)]
35mod tests {
36    use std::future::Future;
37
38    use crate::probe::contract::HttpMethod;
39    use crate::probe::endpoint_contract::EndpointContract;
40    use crate::{BpiClient, BpiResult};
41
42    use super::*;
43
44    fn assert_ip_future<F>(_future: F)
45    where
46        F: Future<Output = BpiResult<IpInfo>>,
47    {
48    }
49
50    #[test]
51    fn clientinfo_client_exposes_ip_endpoint() -> BpiResult<()> {
52        let client = BpiClient::new()?;
53        let clientinfo = client.clientinfo();
54
55        assert_eq!(
56            clientinfo.ip_endpoint(),
57            "https://api.live.bilibili.com/ip_service/v1/ip_service/get_ip_addr"
58        );
59        Ok(())
60    }
61
62    #[test]
63    fn clientinfo_ip_returns_payload_future() -> BpiResult<()> {
64        let client = BpiClient::new()?;
65
66        assert_ip_future(client.clientinfo().ip(ClientInfoIpParams::new()));
67        Ok(())
68    }
69
70    #[test]
71    fn clientinfo_ip_contract_matches_module_client_endpoint() -> BpiResult<()> {
72        let contract = EndpointContract::from_slice(include_bytes!(
73            "../../tests/contracts/clientinfo/ip/contract.json"
74        ))?;
75
76        assert_eq!(contract.name, "clientinfo.ip");
77        assert_eq!(contract.request.method, HttpMethod::Get);
78        assert_eq!(contract.request.url.as_str(), IP_ENDPOINT);
79        assert_eq!(
80            contract.request.query.get("ip").map(String::as_str),
81            Some("8.8.8.8")
82        );
83        Ok(())
84    }
85}