1use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
5use serde::{ Deserialize, Serialize };
6
7#[derive(Debug, Clone, Deserialize, Serialize)]
11pub struct OnlineTotalShowSwitch {
12 pub total: bool,
14 pub count: bool,
16}
17
18#[derive(Debug, Clone, Deserialize, Serialize)]
20pub struct OnlineTotalResponseData {
21 pub total: String,
23 pub count: String,
25 pub show_switch: OnlineTotalShowSwitch,
27}
28
29impl BpiClient {
30 pub async fn video_online_total(
44 &self,
45 aid: Option<u64>,
46 bvid: Option<&str>,
47 cid: u64
48 ) -> Result<BpiResponse<OnlineTotalResponseData>, BpiError> {
49 if aid.is_none() && bvid.is_none() {
50 return Err(BpiError::parse("必须提供 aid 或 bvid"));
51 }
52
53 let mut req = self
54 .get("https://api.bilibili.com/x/player/online/total")
55 .query(&[("cid", &cid.to_string())]);
56
57 if let Some(a) = aid {
58 req = req.query(&[("aid", &a.to_string())]);
59 }
60 if let Some(b) = bvid {
61 req = req.query(&[("bvid", b)]);
62 }
63
64 req.send_bpi("获取视频在线人数").await
65 }
66}
67
68#[cfg(test)]
71mod tests {
72 use super::*;
73 use tracing::info;
74
75 const TEST_AID: u64 = 759949922;
77 const TEST_CID: u64 = 392402545;
78 const TEST_BVID: &str = "BV1y64y1q757";
79
80 #[tokio::test]
81 async fn test_video_online_total_by_aid() -> Result<(), BpiError> {
82 let bpi = BpiClient::new();
83 let resp = bpi.video_online_total(Some(TEST_AID), None, TEST_CID).await?;
84
85 let data = resp.into_data()?;
86
87 info!("视频在线人数: {:?}", data);
88 assert!(!data.count.is_empty());
89 assert!(!data.total.is_empty());
90
91 Ok(())
92 }
93
94 #[tokio::test]
95 async fn test_video_online_total_by_bvid() -> Result<(), BpiError> {
96 let bpi = BpiClient::new();
97 let resp = bpi.video_online_total(None, Some(TEST_BVID), TEST_CID).await?;
98
99 let data = resp.into_data()?;
100
101 info!("视频在线人数: {:?}", data);
102
103 assert!(!data.count.is_empty());
104 assert!(!data.total.is_empty());
105
106 Ok(())
107 }
108}