bpi_rs/video/
online.rs

1//! 视频在线人数相关接口
2//!
3//! 文档: https://github.com/SocialSisterYi/bilibili-API-collect/tree/master/docs/video
4use crate::{BilibiliRequest, BpiClient, BpiError, BpiResponse};
5use serde::{Deserialize, Serialize};
6
7// --- 响应数据结构体 ---
8
9/// 在线人数数据控制
10#[derive(Debug, Clone, Deserialize, Serialize)]
11pub struct OnlineTotalShowSwitch {
12    /// 展示所有终端总计人数
13    pub total: bool,
14    /// 展示web端实时在线人数
15    pub count: bool,
16}
17
18/// 视频在线人数响应数据
19#[derive(Debug, Clone, Deserialize, Serialize)]
20pub struct OnlineTotalResponseData {
21    /// 所有终端总计人数
22    pub total: String,
23    /// web端实时在线人数
24    pub count: String,
25    /// 数据显示控制
26    pub show_switch: OnlineTotalShowSwitch,
27}
28
29impl BpiClient {
30    /// 获取视频在线人数(web端)
31    ///
32    /// 文档: https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/video/online.md
33    ///
34    /// # 参数
35    /// | 名称    | 类型         | 说明                 |
36    /// | ------- | ------------| -------------------- |
37    /// | `aid`   | Option<u64> | 稿件 avid,可选      |
38    /// | `bvid`  | Option<&str>| 稿件 bvid,可选      |
39    /// | `cid`   | u64         | 视频 cid             |
40    ///
41    /// `aid` 和 `bvid` 必须提供一个。
42    pub async fn video_online_total(
43        &self,
44        aid: Option<u64>,
45        bvid: Option<&str>,
46        cid: u64,
47    ) -> Result<BpiResponse<OnlineTotalResponseData>, BpiError> {
48        if aid.is_none() && bvid.is_none() {
49            return Err(BpiError::parse("必须提供 aid 或 bvid"));
50        }
51
52        let mut req = self
53            .get("https://api.bilibili.com/x/player/online/total")
54            .query(&[("cid", &cid.to_string())]);
55
56        if let Some(a) = aid {
57            req = req.query(&[("aid", &a.to_string())]);
58        }
59        if let Some(b) = bvid {
60            req = req.query(&[("bvid", b)]);
61        }
62
63        req.send_bpi("获取视频在线人数").await
64    }
65}
66
67// --- 测试模块 ---
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72    use tracing::info;
73
74    // 假设这是一个已知的视频
75    const TEST_AID: u64 = 759949922;
76    const TEST_CID: u64 = 392402545;
77    const TEST_BVID: &str = "BV1y64y1q757";
78
79    #[tokio::test]
80    async fn test_video_online_total_by_aid() -> Result<(), BpiError> {
81        let bpi = BpiClient::new();
82        let resp = bpi
83            .video_online_total(Some(TEST_AID), None, TEST_CID)
84            .await?;
85
86        let data = resp.into_data()?;
87
88        info!("视频在线人数: {:?}", data);
89        assert!(!data.count.is_empty());
90        assert!(!data.total.is_empty());
91
92        Ok(())
93    }
94
95    #[tokio::test]
96    async fn test_video_online_total_by_bvid() -> Result<(), BpiError> {
97        let bpi = BpiClient::new();
98        let resp = bpi
99            .video_online_total(None, Some(TEST_BVID), TEST_CID)
100            .await?;
101
102        let data = resp.into_data()?;
103
104        info!("视频在线人数: {:?}", data);
105
106        assert!(!data.count.is_empty());
107        assert!(!data.total.is_empty());
108
109        Ok(())
110    }
111}