1use crate::{BilibiliRequest, BpiClient, BpiError, BpiResponse};
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct IpInfo {
14 pub country: Option<String>,
16 pub province: Option<String>,
18 pub city: Option<String>,
20 pub isp: Option<String>,
22 pub addr: Option<String>,
24}
25
26impl BpiClient {
31 pub async fn clientinfo_ip(&self, ip: Option<&str>) -> Result<BpiResponse<IpInfo>, BpiError> {
44 let mut req =
45 self.get("https://api.live.bilibili.com/ip_service/v1/ip_service/get_ip_addr");
46
47 if let Some(ip) = ip {
48 req = req.query(&[("ip", ip)]);
49 }
50
51 req.send_bpi("查询 IP 地址归属地").await
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58
59 const TEST_IP: &str = "8.8.8.8";
60
61 #[tokio::test]
62 async fn test_clientinfo_ip() -> Result<(), Box<BpiError>> {
63 let bpi = BpiClient::new();
64
65 let resp = bpi.clientinfo_ip(Some(TEST_IP)).await?;
66 if resp.code == 0 {
67 if let Some(data) = resp.data {
68 tracing::info!(
69 "IP 地址: {}, 省份: {:?}, 城市: {:?}, ISP: {:?}",
70 data.addr.unwrap_or_default(),
71 data.province,
72 data.city,
73 data.isp
74 );
75 }
76 } else {
77 tracing::error!("请求失败: code={}, message={}", resp.code, resp.message);
78 }
79
80 Ok(())
81 }
82}